"""Routes du module Imports (spec Imports §6).

`CurrentOrgDep` sur **tous** les handlers, sans exception — y compris `POST /imports/files`,
le seul appelé depuis le navigateur : la dérogation de la décision n°8 porte sur l'origine de
l'appel et sur le CORS, jamais sur la vérification du jeton, identique partout.
"""

import uuid
from typing import Annotated

from fastapi import APIRouter, File, Form, Query, UploadFile
from fastapi.responses import FileResponse

from app.core.auth import CurrentOrgDep
from app.db.engine import SessionDep
from app.imports import service, upload
from app.imports.schemas import (
    ImportCreate,
    ImportCreated,
    ImportListOut,
    ImportOut,
    PreviewIn,
    PreviewOut,
    UploadOut,
)

router = APIRouter(prefix="/imports", tags=["imports"])


@router.post("/files", status_code=201)
async def upload_file(
    user: CurrentOrgDep,
    session: SessionDep,
    file: Annotated[UploadFile, File()],
    site_target_id: Annotated[uuid.UUID | None, Form()] = None,
) -> UploadOut:
    """Téléversement direct navigateur → FastAPI (décision n°8) : spool disque + sha256 au vol.

    Le plafond de taille **n'est pas gardé ici** : FastAPI lit le corps avant d'appeler cette
    fonction, c'est donc `UploadSizeGuard` (middleware ASGI, `app/core/upload_guard.py`) qui
    refuse en amont. Ici, le corps est déjà reçu et le jeton déjà vérifié.

    `site_target_id` est facultatif : sans cible, il n'y a pas de doublon à signaler, la
    déduplication étant définie « même sha, **même cible** » (§1.3). L'arbitre reste de toute
    façon `POST /imports`, qui refuse le doublon par un 409 tant que `force` n'est pas posé.
    """
    target = (
        None
        if site_target_id is None
        else await service.get_target(session, user.org_id, site_target_id)
    )
    sha256, size = await upload.spool(file, user.org_id)
    duplicate = (
        None
        if target is None
        else await service.duplicate_import_id(session, user.org_id, target.id, sha256)
    )
    return UploadOut(
        sha256=sha256,
        filename=upload.safe_filename(file.filename),
        size=size,
        duplicate_of=duplicate,
    )


@router.post("/preview")
async def preview(user: CurrentOrgDep, session: SessionDep, payload: PreviewIn) -> PreviewOut:
    return await service.preview(session, user.org_id, payload)


@router.post("", status_code=202)
async def create_import(
    user: CurrentOrgDep, session: SessionDep, payload: ImportCreate
) -> ImportCreated:
    record, job_id = await service.create_import(session, user.org_id, payload)
    return ImportCreated(import_=ImportOut.model_validate(record), job_id=job_id)


@router.get("")
async def list_imports(
    user: CurrentOrgDep,
    session: SessionDep,
    site_target_id: uuid.UUID | None = None,
    cursor: str | None = None,
    limit: Annotated[int, Query(ge=1, le=100)] = 25,
) -> ImportListOut:
    items, next_cursor = await service.list_entries(
        session, user.org_id, site_target_id=site_target_id, cursor=cursor, limit=limit
    )
    return ImportListOut(items=items, next_cursor=next_cursor)


@router.get("/{import_id}")
async def get_import(user: CurrentOrgDep, session: SessionDep, import_id: uuid.UUID) -> ImportOut:
    return ImportOut.model_validate(await service.get_import(session, user.org_id, import_id))


@router.get("/{import_id}/errors.csv")
async def download_errors(
    user: CurrentOrgDep, session: SessionDep, import_id: uuid.UUID
) -> FileResponse:
    path = await service.errors_csv(session, user.org_id, import_id)
    return FileResponse(
        path,
        media_type="text/csv",
        filename=f"import-{import_id}-errors.csv",
    )
