import os
from uuid import uuid4
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from sqlalchemy.orm import Session
from typing import Optional, List
from pydantic import BaseModel
from models.models_profile_tables import RecruiterProfile
from database import SessionLocal
from models.user_model import User
from models.service_model import Service, ServiceCategory
from models.job_application_model import JobApplication

router = APIRouter()
UPLOAD_DIR = "uploads"
os.makedirs(UPLOAD_DIR, exist_ok=True)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# -------------------------
# Recruiter creates a job
# -------------------------
class JobCreate(BaseModel):
    recruiter_id: int
    job_title: str
    job_description: str
    location: str
    category: Optional[str] = None
    company_name: str
    company_logo: Optional[str] = None
    company_rating: Optional[float] = None
    salary_inr: Optional[str] = None
    salary_usd: Optional[str] = None
    job_type: Optional[str] = None
    responsibilities: Optional[str] = None
    requirements: Optional[str] = None
    tech_stack: Optional[str] = None
    benefits: Optional[str] = None
    apply_link: Optional[str] = None

@router.post("/job/create")
def create_job(job: JobCreate, db: Session = Depends(get_db)):
    recruiter = db.query(RecruiterProfile).filter(RecruiterProfile.user_id == job.recruiter_id).first()
    if not recruiter:
        raise HTTPException(status_code=404, detail="Recruiter not found")

    # Validate category
    try:
        category_enum = ServiceCategory[job.category.replace(" ", "_").upper()] if job.category else None
    except KeyError:
        raise HTTPException(
            status_code=400,
            detail=f"Invalid category. Valid categories: {[c.value for c in ServiceCategory]}"
        )

    new_job = Service(
        recruiter_id=job.recruiter_id,
        job_title=job.job_title,
        job_description=job.job_description,
        job_location=job.location,
        company_name=job.company_name,
        company_logo=job.company_logo,
        company_rating=job.company_rating,
        salary_inr=job.salary_inr,
        salary_usd=job.salary_usd,
        job_type=job.job_type,
        responsibilities=job.responsibilities,
        requirements=job.requirements,
        tech_stack=job.tech_stack,
        benefits=job.benefits,
        apply_link=job.apply_link,
        service_category=category_enum,
        status="active",
        created_at=datetime.utcnow().isoformat()
    )
    db.add(new_job)
    db.commit()
    db.refresh(new_job)
    return {"message": "Job created successfully", "job_id": new_job.id}


# -------------------------
# Apply to job with CV and video
# -------------------------
@router.post("/job/apply/upload")
async def apply_with_upload(
    user_id: int = Form(...),
    service_id: int = Form(...),
    cv_file: UploadFile = File(...),
    video_file: UploadFile = File(...),
    db: Session = Depends(get_db)
):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    job = db.query(Service).filter(Service.id == service_id).first()
    if not job:
        raise HTTPException(status_code=404, detail="Job not found")

    existing = db.query(JobApplication).filter(
        JobApplication.user_id == user_id,
        JobApplication.service_id == service_id
    ).first()
    if existing:
        raise HTTPException(status_code=400, detail="Already applied to this job")

    # Save files
    cv_filename = f"{uuid4()}_{cv_file.filename}"
    cv_path = os.path.join(UPLOAD_DIR, cv_filename)
    with open(cv_path, "wb") as f:
        content = await cv_file.read()
        f.write(content)

    video_filename = f"{uuid4()}_{video_file.filename}"
    video_path = os.path.join(UPLOAD_DIR, video_filename)
    with open(video_path, "wb") as f:
        content = await video_file.read()
        f.write(content)

    app = JobApplication(
        user_id=user_id,
        service_id=service_id,
        applied_at=datetime.utcnow(),
        cv_path=cv_path,
        video_path=video_path
    )
    db.add(app)
    db.commit()
    db.refresh(app)

    return {
        "message": "Application submitted successfully with files.",
        "job_title": job.job_title,
        "cv_path": cv_path,
        "video_path": video_path
    }

# -------------------------
# Recruiter views applicants
# -------------------------
@router.get("/recruiter/applications/{job_id}")
def get_applicants(job_id: int, db: Session = Depends(get_db)):
    job = db.query(Service).filter(Service.id == job_id).first()
    if not job:
        raise HTTPException(status_code=404, detail="Job not found")

    applications = db.query(JobApplication).filter(JobApplication.service_id == job_id).all()
    result = []
    for app in applications:
        user = db.query(User).filter(User.id == app.user_id).first()
        result.append({
            "applicant_id": user.id,
            "name": user.name,
            "email": user.email,
            "applied_at": app.applied_at,
            "cv_path": app.cv_path.replace("\\", "/"),
            "video_path": app.video_path.replace("\\", "/")

        })

    return result

@router.get("/recruiter/{recruiter_id}/jobs")
def get_jobs_by_recruiter(recruiter_id: int, db: Session = Depends(get_db)):
    jobs = db.query(Service).filter(Service.recruiter_id == recruiter_id).all()

    if not jobs:
        raise HTTPException(status_code=404, detail="No jobs found for this recruiter")

    result = []
    for job in jobs:
        result.append({
            "id": job.id,
            "recruiter_id": job.recruiter_id,
            "job_title": job.job_title,
            "job_description": job.job_description,
            "location": job.job_location,
            "category": job.service_category.value if job.service_category else None,
            "company_name": job.company_name,
            "company_logo": job.company_logo,
            "company_rating": job.company_rating,
            "salary_inr": job.salary_inr,
            "salary_usd": job.salary_usd,
            "job_type": job.job_type,
            "responsibilities": job.responsibilities,
            "requirements": job.requirements,
            "tech_stack": job.tech_stack,
            "benefits": job.benefits,
            "apply_link": job.apply_link,
            "status": job.status.value if job.status else None,
            "created_at": job.created_at,
            "updated_at": job.updated_at
        })

    return {"jobs": result}

@router.get("/all-jobs")
def get_all_jobs(db: Session = Depends(get_db)):
    jobs = db.query(Service).all()

    if not jobs:
        raise HTTPException(status_code=404, detail="No jobs found")

    result = []
    for job in jobs:
        result.append({
            "id": job.id,
            "recruiter_id": job.recruiter_id,
            "job_title": job.job_title,
            "job_description": job.job_description,
            "location": job.job_location,
            "category": job.service_category.value if job.service_category else None,
            "company_name": job.company_name,
            "company_logo": job.company_logo,
            "company_rating": job.company_rating,
            "salary_inr": job.salary_inr,
            "salary_usd": job.salary_usd,
            "job_type": job.job_type,
            "responsibilities": job.responsibilities,
            "requirements": job.requirements,
            "tech_stack": job.tech_stack,
            "benefits": job.benefits,
            "apply_link": job.apply_link,
            "status": job.status.value if job.status else None,
            "created_at": job.created_at,
            "updated_at": job.updated_at
        })

    return {"jobs": result}




@router.get("/user/{user_id}/applied-jobs")
def get_jobs_applied_by_user(user_id: int, db: Session = Depends(get_db)):
    applications = db.query(JobApplication).filter(JobApplication.user_id == user_id).all()
    result = []
    for app in applications:
        job = db.query(Service).filter(Service.id == app.service_id).first()
        result.append({
            "job_id": job.id,
            "job_title": job.job_title,
            "job_location": job.job_location,
            "applied_at": app.applied_at,
            "cv_path": app.cv_path,
            "video_path": app.video_path
        })
    return result

from fastapi.responses import StreamingResponse
from fastapi import Request

@router.get("/uploads/{filename}")
async def stream_file(filename: str, request: Request):
    file_path = os.path.join(UPLOAD_DIR, filename)

    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="File not found")

    file_size = os.path.getsize(file_path)
    range_header = request.headers.get("range")

    def file_iterator(start=0, end=None):
        with open(file_path, "rb") as f:
            f.seek(start)
            remaining = (end - start + 1) if end else None
            while True:
                chunk_size = 1024 * 1024
                if remaining is not None:
                    chunk_size = min(chunk_size, remaining)
                data = f.read(chunk_size)
                if not data:
                    break
                if remaining is not None:
                    remaining -= len(data)
                yield data

    if range_header:
        start, end = 0, file_size - 1
        match = range_header.strip().split("=")[-1]
        if "-" in match:
            parts = match.split("-")
            start = int(parts[0]) if parts[0] else 0
            end = int(parts[1]) if parts[1] else file_size - 1

        if start >= file_size:
            raise HTTPException(status_code=416, detail="Range Not Satisfiable")

        headers = {
            "Content-Range": f"bytes {start}-{end}/{file_size}",
            "Accept-Ranges": "bytes",
            "Content-Length": str(end - start + 1),
            "Content-Type": "video/mp4"
        }

        return StreamingResponse(file_iterator(start, end), status_code=206, headers=headers)

    headers = {
        "Content-Length": str(file_size),
        "Content-Type": "video/mp4"
    }
    return StreamingResponse(file_iterator(), headers=headers)
