from __future__ import annotations

from typing import TYPE_CHECKING, Annotated, Any

from fastapi import APIRouter, Body, Depends, File, Form, HTTPException, UploadFile
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ConfigDict
from starlette import status

from app.auth import get_current_user
from app.core.dependencies import get_services
from app.models import UserInDB


if TYPE_CHECKING:
    from app.core.services import AppServices
else:
    AppServices = Any


CurrentUser = Annotated[UserInDB, Depends(get_current_user)]
ServicesDep = Annotated[AppServices, Depends(get_services)]

router = APIRouter()


class ConfirmIndividualUploadBody(BaseModel):
    model_config = ConfigDict(extra="ignore")

    case_number: str = ""
    patient_id: str = ""
    patient_name: str = ""
    effective_document_type: str = ""


class CancelIndividualUploadBody(BaseModel):
    model_config = ConfigDict(extra="ignore")

    reason: str = ""


@router.post("/api/cargue-individual/historia")
async def create_individual_story_upload(
    file: Annotated[UploadFile, File(...)],
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    try:
        contents = await file.read()
        result = services.individual_ingestion_runtime.create_upload.execute(
            filename=file.filename or "",
            contents=contents,
            username=current_user.username,
            selected_document_type="historia_clinica",
        )
        return JSONResponse(status_code=status.HTTP_202_ACCEPTED, content=result)
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))


@router.post("/api/cargue-individual/soporte")
async def create_individual_support_upload(
    file: Annotated[UploadFile, File(...)],
    tipo_documento: Annotated[str, Form(...)],
    case_key: Annotated[str, Form(...)],
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    try:
        contents = await file.read()
        result = services.individual_ingestion_runtime.create_upload.execute(
            filename=file.filename or "",
            contents=contents,
            username=current_user.username,
            selected_document_type=str(tipo_documento or "").strip(),
            provided_case_key=str(case_key or "").strip(),
        )
        return JSONResponse(status_code=status.HTTP_202_ACCEPTED, content=result)
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))


@router.get("/api/cargue-individual/pending-latest")
async def get_latest_pending_individual_upload(
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    payload = services.individual_ingestion_runtime.get_latest_pending.execute(current_user.username)
    return JSONResponse(status_code=status.HTTP_200_OK, content={"upload": payload})


@router.get("/api/cargue-individual/{upload_id}")
async def get_individual_upload_status(
    upload_id: str,
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    payload = services.individual_ingestion_runtime.get_upload_status.execute(
        upload_id,
        username=current_user.username,
    )
    if payload is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Carga individual no encontrada.")
    return JSONResponse(status_code=status.HTTP_200_OK, content=payload)


@router.post("/api/cargue-individual/{upload_id}/confirmar")
async def confirm_individual_upload(
    upload_id: str,
    body: Annotated[ConfirmIndividualUploadBody, Body(default_factory=ConfirmIndividualUploadBody)],
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    try:
        payload = services.individual_ingestion_runtime.confirm_upload.execute(
            upload_id=upload_id,
            username=current_user.username,
            confirmed_case_number=body.case_number,
            confirmed_patient_id=body.patient_id,
            confirmed_patient_name=body.patient_name,
            confirmed_effective_document_type=body.effective_document_type,
        )
        return JSONResponse(
            status_code=status.HTTP_202_ACCEPTED,
            content={"upload_id": upload_id, "status": payload.get("status", "")},
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))


@router.post("/api/cargue-individual/{upload_id}/cancelar")
async def cancel_individual_upload(
    upload_id: str,
    body: Annotated[CancelIndividualUploadBody, Body(default_factory=CancelIndividualUploadBody)],
    current_user: CurrentUser,
    services: ServicesDep,
) -> JSONResponse:
    try:
        payload = services.individual_ingestion_runtime.cancel_upload.execute(
            upload_id=upload_id,
            username=current_user.username,
            reason=body.reason,
        )
        return JSONResponse(
            status_code=status.HTTP_200_OK,
            content={"upload_id": upload_id, "status": payload.get("status", "")},
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
