"""Rich-formatted eval result reporter and HTML report generator."""

from __future__ import annotations

from datetime import datetime
from pathlib import Path

from jinja2 import Environment, FileSystemLoader
from rich.table import Table

from hatchdx.eval.models import EvalResult, EvalSuite
from hatchdx.eval.storage import Regression
from hatchdx.utils.console import console


def report_eval_results(
    results_by_suite: dict[str, list[EvalResult]],
    suites: list[EvalSuite],
    *,
    regressions: list[Regression] | None = None,
) -> int:
    """Print eval results for all suites and return exit code (0 = all passed).

    Returns 0 if everything passed, 1 if any eval failed.
    """
    total_passed = 0
    total_failed = 0
    total_ms = 0.0

    suite_lookup = {s.name: s for s in suites}

    for suite_name, results in results_by_suite.items():
        suite = suite_lookup.get(suite_name)
        description = suite.description if suite else ""

        # Suite header
        console.print(f"\n[bold]{suite_name}[/]")
        if description:
            console.print(f"[dim]{description}[/]")
        console.print()

        # Results table
        table = Table(show_edge=False, pad_edge=False)
        table.add_column("Eval", style="bold")
        table.add_column("Status", justify="center")
        table.add_column("Assertions", justify="center")
        table.add_column("Latency", justify="right")
        table.add_column("Details", style="dim")

        for result in results:
            status = "[green]pass[/]" if result.passed else "[red]FAIL[/]"
            latency = f"{result.latency_ms:.0f}ms"

            passed_assertions = sum(1 for a in result.assertion_results if a.passed)
            total_assertions = len(result.assertion_results)
            assertion_summary = f"{passed_assertions}/{total_assertions}"

            # Show first failure reason if any
            details = ""
            for ao in result.assertion_results:
                if not ao.passed:
                    details = ao.reason
                    break
            if len(details) > 60:
                details = details[:57] + "..."

            table.add_row(
                result.eval_case.name,
                status,
                assertion_summary,
                latency,
                details,
            )

            if result.passed:
                total_passed += 1
            else:
                total_failed += 1
            total_ms += result.latency_ms

        console.print(table)

    # Regression warnings
    if regressions:
        console.print()
        for reg in regressions:
            console.print(
                f"[bold yellow]regression[/] {reg.eval_name} "
                f"in suite '{reg.suite_name}' — passed previously, now fails"
            )

    # Summary footer
    console.print()
    if total_failed == 0:
        console.print(
            f"[bold green]Eval results: {total_passed} passed[/] "
            f"({total_ms:.0f}ms total)"
        )
    else:
        console.print(
            f"[bold red]Eval results: {total_passed} passed, {total_failed} failed[/] "
            f"({total_ms:.0f}ms total)"
        )

    return 0 if total_failed == 0 else 1


def generate_html_report(
    results_by_suite: dict[str, list[EvalResult]],
    suites: list[EvalSuite],
    output_path: Path,
    *,
    regressions: list[Regression] | None = None,
) -> Path:
    """Generate a standalone HTML report file.

    Returns the path to the generated file.
    """
    suite_lookup = {s.name: s for s in suites}

    total_passed = sum(
        1 for results in results_by_suite.values()
        for r in results if r.passed
    )
    total_failed = sum(
        1 for results in results_by_suite.values()
        for r in results if not r.passed
    )
    total_ms = sum(
        r.latency_ms for results in results_by_suite.values()
        for r in results
    )

    # Build template context data
    suite_data = []
    for suite_name, results in results_by_suite.items():
        suite = suite_lookup.get(suite_name)
        rows = []
        for result in results:
            passed_assertions = sum(1 for a in result.assertion_results if a.passed)
            details = ""
            for ao in result.assertion_results:
                if not ao.passed:
                    details = ao.reason
                    break
            rows.append({
                "eval_name": result.eval_case.name,
                "status_class": "pass" if result.passed else "fail",
                "status_text": "PASS" if result.passed else "FAIL",
                "passed_assertions": passed_assertions,
                "total_assertions": len(result.assertion_results),
                "latency_ms": f"{result.latency_ms:.0f}",
                "details": details,
            })
        suite_data.append({
            "name": suite_name,
            "description": suite.description if suite else "",
            "rows": rows,
        })

    template_dir = Path(__file__).parent / "templates"
    env = Environment(
        loader=FileSystemLoader(str(template_dir)),
        autoescape=True,
    )
    template = env.get_template("eval_report.html")

    html_content = template.render(
        generated_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        total_passed=total_passed,
        total_failed=total_failed,
        total_ms=f"{total_ms:.0f}",
        num_suites=len(results_by_suite),
        regressions=regressions,
        suite_data=suite_data,
    )

    output_path = Path(output_path)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(html_content, encoding="utf-8")

    return output_path
