from __future__ import annotations

from pathlib import Path

from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session

from evalkit.models import EvaluationResult, MetricScore, TestCase
from evalkit.reports.generator import ReportGenerator
from evalkit.server.db.models import EvaluationModel, EvaluationStatus
from evalkit.server.db.session import get_db

router = APIRouter()
templates = Jinja2Templates(directory=str(Path(__file__).parent.parent / "templates"))


@router.get("/evaluations/{evaluation_id}", response_class=HTMLResponse)
def evaluation_detail(evaluation_id: int, request: Request, db: Session = Depends(get_db)):
    evaluation = db.get(EvaluationModel, evaluation_id)
    if evaluation is None:
        raise HTTPException(status_code=404, detail="Evaluation not found")

    prev_evaluation = (
        db.query(EvaluationModel)
        .filter(
            EvaluationModel.project_id == evaluation.project_id,
            EvaluationModel.id != evaluation.id,
            EvaluationModel.status == EvaluationStatus.complete,
            EvaluationModel.id < evaluation.id,
        )
        .order_by(EvaluationModel.id.desc())
        .first()
    )

    return templates.TemplateResponse(
        request,
        "evaluation.html",
        {
            "evaluation": evaluation,
            "prev_evaluation": prev_evaluation,
        },
    )


@router.get("/evaluations/{evaluation_id}/report")
def download_report(evaluation_id: int, db: Session = Depends(get_db)):
    evaluation = db.get(EvaluationModel, evaluation_id)
    if evaluation is None:
        raise HTTPException(status_code=404, detail="Evaluation not found")

    # Rebuild EvaluationResults from DB to regenerate suggestions
    eval_results: list[EvaluationResult] = []
    for r in evaluation.results:
        tc = TestCase.model_validate_json(r.test_case_json)
        scores = [
            MetricScore(
                metric_name=ms.metric_name,
                score=ms.score,
                passed=bool(ms.passed),
                reason=ms.reason,
            )
            for ms in r.metric_scores
        ]
        eval_results.append(EvaluationResult(test_case=tc, scores=scores))

    generator = ReportGenerator()
    report = generator.generate(eval_results, evaluation.suite_name)

    results_data = [
        {
            "test_case": r.get_test_case_dict(),
            "overall_score": r.overall_score,
            "metric_scores": [
                {"metric_name": ms.metric_name, "score": ms.score, "passed": bool(ms.passed), "reason": ms.reason}
                for ms in r.metric_scores
            ],
        }
        for r in evaluation.results
    ]

    return JSONResponse(
        content={
            "suite_name": evaluation.suite_name,
            "average_score": evaluation.average_score,
            "status": evaluation.status.value,
            "results": results_data,
            "summary": {
                "total_cases": report.summary.total_cases,
                "passed": report.summary.passed,
                "failed": report.summary.failed,
                "score_by_metric": report.summary.score_by_metric,
            },
            "failures": [
                {
                    "failure_type": fg.failure_type,
                    "count": fg.count,
                    "severity": fg.severity,
                    "average_score": fg.average_score,
                    "suggestion": fg.suggestion,
                    "patterns": fg.patterns,
                }
                for fg in report.failures
            ],
        }
    )
