from __future__ import annotations

import threading
import uuid
from pathlib import Path

from fastapi import FastAPI, UploadFile, File, Form, Request
from fastapi.responses import HTMLResponse, FileResponse, JSONResponse
from fastapi.templating import Jinja2Templates

from app.services.job_store import jobs
from app.services.subtitle_service import translate_srt_content, parse_srt

app = FastAPI()
templates = Jinja2Templates(directory="app/templates")

OUTPUT_DIR = Path("data/output")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)


@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
    return templates.TemplateResponse(
        request=request,
        name="index.html",
        context={},
    )


@app.post("/start")
async def start_translation(
    file: UploadFile = File(...),
    mode: str = Form("fast"),
    source_lang: str = Form("auto"),
    target_lang: str = Form("da"),
    model: str = Form("gpt-4o-mini"),
    workers: int = Form(4),
):
    try:
        raw = await file.read()
        content = raw.decode("utf-8-sig")
    except UnicodeDecodeError:
        return JSONResponse(
            {"error": "Kunne ikke læse filen som UTF-8/UTF-8-SIG"},
            status_code=400,
        )

    if workers < 1:
        workers = 1
    if workers > 16:
        workers = 16

    job_id = str(uuid.uuid4())
    output_path = OUTPUT_DIR / f"{job_id}.srt"

    try:
        parsed_blocks = parse_srt(content)
        block_count = len(parsed_blocks)
    except Exception:
        block_count = 0

    jobs[job_id] = {
        "status": "queued",
        "progress": 0,
        "filename": file.filename or "translated.srt",
        "output_path": str(output_path),
        "blocks": block_count,
        "error": "",
        "done": False,
        "mode": mode,
        "source_lang": source_lang,
        "target_lang": target_lang,
        "model": model,
        "workers": workers,
    }

    def progress_callback(done_blocks: int, total_blocks: int):
        if total_blocks <= 0:
            jobs[job_id]["progress"] = 1
            return

        percent = int((done_blocks / total_blocks) * 100)

        if done_blocks > 0:
            percent = max(2, percent)

        percent = min(99, percent)

        jobs[job_id]["progress"] = percent
        jobs[job_id]["status"] = "running"
        jobs[job_id]["blocks"] = total_blocks

    def worker():
        try:
            jobs[job_id]["status"] = "starting"
            jobs[job_id]["progress"] = 1

            translated_srt = translate_srt_content(
                content=content,
                mode=mode,
                source_lang=source_lang,
                target_lang=target_lang,
                job_id=job_id,
                progress_callback=progress_callback,
                model=model,
                workers=workers,
            )

            output_path.write_text(translated_srt, encoding="utf-8")

            jobs[job_id]["status"] = "done"
            jobs[job_id]["progress"] = 100
            jobs[job_id]["done"] = True

        except Exception as e:
            jobs[job_id]["status"] = "error"
            jobs[job_id]["progress"] = 0
            jobs[job_id]["error"] = str(e)
            jobs[job_id]["done"] = False

    threading.Thread(target=worker, daemon=True).start()

    return JSONResponse({"job_id": job_id})


@app.get("/status/{job_id}")
async def get_status(job_id: str):
    job = jobs.get(job_id)
    if not job:
        return JSONResponse(
            {"status": "unknown", "progress": 0, "error": "Job not found"},
            status_code=404,
        )
    return JSONResponse(job)


@app.get("/download/{job_id}")
async def download_result(job_id: str):
    job = jobs.get(job_id)
    if not job:
        return JSONResponse({"error": "Job not found"}, status_code=404)

    if not job.get("done"):
        return JSONResponse({"error": "File not ready yet"}, status_code=400)

    path = Path(job["output_path"])
    if not path.exists():
        return JSONResponse({"error": "Output file missing"}, status_code=404)

    original_name = job.get("filename", "translated.srt")
    download_name = f"translated_{original_name}"

    return FileResponse(
        path=path,
        media_type="application/x-subrip",
        filename=download_name,
    )
