from typing import Any

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel

from backend.config import PROJECT_ROOT
from backend.label_service import (
    get_public_response,
    label_one,
    read_prompt,
    read_samples,
    validate_task,
)
from backend.sample_generator import (
    generate_sample,
    get_generated_sample,
    list_generated_samples,
)


app = FastAPI(title="金融文本统一打标系统")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

FRONTEND_DIR = PROJECT_ROOT / "frontend"
app.mount("/static", StaticFiles(directory=FRONTEND_DIR), name="static")


class LabelRequest(BaseModel):
    task: str
    sample_id: str | None = None
    text: str | None = None
    text_a: str | None = None
    text_b: str | None = None


class GenerateSampleRequest(BaseModel):
    task: str
    difficulty: str


@app.get("/")
def index() -> FileResponse:
    return FileResponse(FRONTEND_DIR / "index.html")


@app.get("/prompt/{task}")
def get_prompt(task: str) -> dict[str, str]:
    try:
        return {"task": task, "prompt": read_prompt(task)}
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc


@app.get("/samples/{task}")
def get_samples(task: str, difficulty: str | None = None) -> dict[str, Any]:
    try:
        file_samples = read_samples(task, difficulty)
        generated_samples = list_generated_samples(task, difficulty)
        return {
            "task": task,
            "difficulty": difficulty,
            "samples": generated_samples + file_samples,
        }
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc


@app.post("/generate-sample")
def generate_sample_api(request: GenerateSampleRequest) -> dict[str, Any]:
    try:
        validate_task(request.task)
        sample = generate_sample(request.task, request.difficulty)
        return {"task": request.task, "sample": sample}
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    except RuntimeError as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc
    except Exception as exc:
        raise HTTPException(
            status_code=500,
            detail=f"生成测试数据时发生异常：{exc}",
        ) from exc


@app.post("/label")
def label(request: LabelRequest) -> dict[str, Any]:
    try:
        validate_task(request.task)
        payload = request.model_dump(exclude_none=True)
        task = payload.pop("task")
        sample_id = payload.pop("sample_id", None)

        sample = None
        if sample_id:
            sample = get_generated_sample(sample_id) or next(
                (
                    item
                    for item in read_samples(task)
                    if item.get("id") == sample_id
                ),
                None,
            )
            if sample is None:
                raise ValueError(f"未找到示例数据：{sample_id}")

        record = label_one(task, payload, sample=sample)
        return get_public_response(record)
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    except RuntimeError as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc
