from __future__ import annotations

import mimetypes
import time
import uuid
from pathlib import Path

from fastapi import FastAPI, File, Form, HTTPException, UploadFile
from fastapi.responses import FileResponse, HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles

from .blur_engine import IMAGE_EXTS, VIDEO_EXTS, SensitiveDetector, is_image, is_video, preview_frame, process_image, process_video

BASE_DIR = Path(__file__).resolve().parents[1]
UPLOAD_DIR = BASE_DIR / "uploads"
OUTPUT_DIR = BASE_DIR / "outputs"
STATIC_DIR = BASE_DIR / "static"

app = FastAPI(title="Auto Intimate Blur", version="1.0.0")
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
_detector: SensitiveDetector | None = None


def detector() -> SensitiveDetector:
    global _detector
    if _detector is None:
        _detector = SensitiveDetector(score_threshold=0.25)
    return _detector


@app.get("/health")
def health():
    return {"status": "ok", "app": "auto-intimate-blur"}


@app.get("/", response_class=HTMLResponse)
def index():
    return FileResponse(STATIC_DIR / "index.html")


def _find_upload(file_id: str) -> Path:
    safe_id = Path(file_id).stem
    matches = list(UPLOAD_DIR.glob(f"{safe_id}.*"))
    if not matches:
        raise HTTPException(status_code=404, detail="Upload introuvable")
    return matches[0]


@app.post("/api/upload")
async def upload_file(file: UploadFile = File(...)):
    original_name = Path(file.filename or "upload").name
    ext = Path(original_name).suffix.lower()
    if ext not in IMAGE_EXTS | VIDEO_EXTS:
        raise HTTPException(status_code=400, detail=f"Format non supporté: {ext}")
    UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
    file_id = f"{int(time.time())}_{uuid.uuid4().hex[:8]}"
    input_path = UPLOAD_DIR / f"{file_id}{ext}"
    with input_path.open("wb") as f:
        while chunk := await file.read(1024 * 1024):
            f.write(chunk)
    return JSONResponse({
        "ok": True,
        "file_id": file_id,
        "filename": original_name,
        "kind": "image" if ext in IMAGE_EXTS else "video",
    })


@app.post("/api/preview")
async def preview_upload(
    file_id: str = Form(...),
    blur_strength: int = Form(71),
    margin: float = Form(0.20),
    frame_index: int = Form(0),
):
    input_path = _find_upload(file_id)
    preview_path = OUTPUT_DIR / f"{Path(file_id).stem}_preview.png"
    try:
        meta = preview_frame(input_path, preview_path, detector(), blur_strength=blur_strength, margin=margin, frame_index=frame_index)
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc
    return JSONResponse({
        "ok": True,
        "preview_url": f"/download/{preview_path.name}",
        "meta": meta,
    })


@app.post("/api/render")
async def render_upload(
    file_id: str = Form(...),
    blur_strength: int = Form(71),
    margin: float = Form(0.20),
    detect_every: int = Form(5),
):
    input_path = _find_upload(file_id)
    out_ext = ".png" if is_image(input_path) else ".mp4"
    output_path = OUTPUT_DIR / f"{Path(file_id).stem}_blurred{out_ext}"
    try:
        det = detector()
        if is_image(input_path):
            meta = process_image(input_path, output_path, det, blur_strength=blur_strength, margin=margin)
        elif is_video(input_path):
            meta = process_video(input_path, output_path, det, blur_strength=blur_strength, margin=margin, detect_every=detect_every)
        else:
            raise HTTPException(status_code=400, detail="Type non supporté")
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc
    return JSONResponse({
        "ok": True,
        "filename": output_path.name,
        "download_url": f"/download/{output_path.name}",
        "preview_url": f"/download/{output_path.name}",
        "meta": meta,
    })


@app.post("/api/process")
async def process_upload_legacy(
    file: UploadFile = File(...),
    blur_strength: int = Form(71),
    margin: float = Form(0.20),
    detect_every: int = Form(5),
):
    uploaded = await upload_file(file)
    data = uploaded.body
    import json
    file_id = json.loads(data)["file_id"]
    return await render_upload(file_id=file_id, blur_strength=blur_strength, margin=margin, detect_every=detect_every)


@app.get("/download/{filename}")
def download(filename: str):
    safe = Path(filename).name
    path = OUTPUT_DIR / safe
    if not path.exists():
        raise HTTPException(status_code=404, detail="Fichier introuvable")
    media_type = mimetypes.guess_type(str(path))[0] or "application/octet-stream"
    return FileResponse(path, media_type=media_type, filename=safe)
