from __future__ import annotations

from pathlib import Path

from fastapi import FastAPI, File, Form, HTTPException, Request, UploadFile
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import ValidationError

from app.audio_transcriber import AudioTranscriptionError, transcribe_audio_bytes
from app.ai_interpreter import extraction_form_values, interpret_oee_case, missing_labels
from app.models import (
    AudioTranscriptionResponse,
    InterpretationRequest,
    OEEInput,
    OEEInterpretationResponse,
    OEEResult,
)
from app.oee_calculator import calculate_oee
from app.validators import parse_oee_form, validation_messages

BASE_DIR = Path(__file__).resolve().parent

app = FastAPI(
    title="CALCOEE",
    description="Calculadora OEE con interprete IA para casos en texto libre.",
    version="0.1.0",
)

app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
templates = Jinja2Templates(directory=BASE_DIR / "templates")


def pct(value: float) -> str:
    return f"{value * 100:.2f}%"


def qty(value: float) -> str:
    number = float(value)
    if number.is_integer():
        return f"{int(number)}"
    return f"{number:.4f}".rstrip("0").rstrip(".")


templates.env.filters["pct"] = pct
templates.env.filters["qty"] = qty


@app.get("/health")
def health() -> dict[str, str]:
    return {"status": "ok"}


@app.get("/", response_class=HTMLResponse)
async def manual_form(request: Request) -> HTMLResponse:
    return templates.TemplateResponse(
        request,
        "index.html",
        {
            "request": request,
            "active": "manual",
            "form": {},
            "errors": [],
        },
    )


@app.post("/calculate", response_class=HTMLResponse)
async def calculate_view(
    request: Request,
    tiempo_turno_min: str = Form(...),
    paradas_planificadas_min: str = Form("0"),
    paradas_no_planificadas_min: str = Form("0"),
    produccion_total: str = Form(...),
    produccion_buena: str = Form(...),
    ciclo_ideal_seg: str = Form(...),
    unidad_produccion: str = Form("unidades"),
) -> HTMLResponse:
    form = {
        "tiempo_turno_min": tiempo_turno_min,
        "paradas_planificadas_min": paradas_planificadas_min,
        "paradas_no_planificadas_min": paradas_no_planificadas_min,
        "produccion_total": produccion_total,
        "produccion_buena": produccion_buena,
        "ciclo_ideal_seg": ciclo_ideal_seg,
        "unidad_produccion": unidad_produccion,
    }

    try:
        entrada = parse_oee_form(form)
        result = calculate_oee(entrada)
    except (ValidationError, ValueError) as exc:
        return templates.TemplateResponse(
            request,
            "index.html",
            {
                "request": request,
                "active": "manual",
                "form": form,
                "errors": validation_messages(exc),
            },
            status_code=422,
        )

    return templates.TemplateResponse(
        request,
        "result.html",
        {
            "request": request,
            "active": "manual",
            "source": "manual",
            "result": result,
            "form": form,
            "extraction": None,
            "missing": [],
            "case_text": "",
        },
    )


@app.get("/interpret", response_class=HTMLResponse)
async def interpret_form(request: Request) -> HTMLResponse:
    return templates.TemplateResponse(
        request,
        "interpret.html",
        {
            "request": request,
            "active": "interpret",
            "case_text": "",
            "form": {},
            "errors": [],
            "extraction": None,
            "missing": [],
        },
    )


@app.post("/interpret", response_class=HTMLResponse)
async def interpret_view(
    request: Request,
    case_text: str = Form(...),
) -> HTMLResponse:
    response = interpret_oee_case(case_text)
    form = extraction_form_values(response.extraccion)

    if response.resultado:
        return templates.TemplateResponse(
            request,
            "result.html",
            {
                "request": request,
                "active": "interpret",
                "source": "interpret",
                "result": response.resultado,
                "form": form,
                "extraction": response.extraccion,
                "missing": [],
                "case_text": case_text,
            },
        )

    return templates.TemplateResponse(
        request,
        "interpret.html",
        {
            "request": request,
            "active": "interpret",
            "case_text": case_text,
            "form": form,
            "errors": response.extraccion.advertencias,
            "extraction": response.extraccion,
            "missing": missing_labels(response.extraccion),
        },
        status_code=422 if response.extraccion.estado != "completo" else 200,
    )


@app.post("/api/oee/calculate", response_model=OEEResult)
async def api_calculate(payload: OEEInput) -> OEEResult:
    return calculate_oee(payload)


@app.post("/api/oee/interpret", response_model=OEEInterpretationResponse)
async def api_interpret(payload: InterpretationRequest) -> OEEInterpretationResponse:
    return interpret_oee_case(payload.text)


@app.post("/api/audio/transcribe", response_model=AudioTranscriptionResponse)
async def api_audio_transcribe(
    audio: UploadFile = File(...),
    language: str = Form("es"),
) -> AudioTranscriptionResponse:
    audio_bytes = await audio.read()
    try:
        text = transcribe_audio_bytes(
            audio_bytes=audio_bytes,
            file_name=audio.filename or "dictado.webm",
            content_type=audio.content_type,
            language=language,
        )
    except AudioTranscriptionError as exc:
        raise HTTPException(status_code=422, detail=str(exc)) from exc

    return AudioTranscriptionResponse(text=text)
