"""Triage orchestration — runs checks and produces a verdict."""

from pydantic import BaseModel

from noisegate.builtins import BuiltinChecks, _triage_user_message
from noisegate.checks import create_plugin_manager
from noisegate.exceptions import NoiseGateError
from noisegate.llm import run_structured_llm_call
from noisegate.models import Check, CheckResult, ChecksResult, Policy, Program, Report
from noisegate.policy import derive_verdict


class _SummaryOutput(BaseModel):
    summary: str


def _run_summary(
    results: list[CheckResult], report: Report, program: Program, model: str,
) -> tuple[str, int, int]:
    """Generate a holistic summary. Returns (summary, prompt_tokens, completion_tokens)."""
    checks_text = "\n".join(
        f"- {r.check_id}: {'PASS' if r.passed else 'FAIL'} — {r.reason}"
        for r in results
    )
    user_message = f"""\
{_triage_user_message(report, program)}
---

## Check Results

{checks_text}

Provide your holistic assessment.
"""
    output, prompt_tokens, completion_tokens = run_structured_llm_call(
        model=model,
        output_type=_SummaryOutput,
        system_prompt=(
            "You are a bug bounty triage analyst. You have evaluated a vulnerability report "
            "against a set of checks. Provide a 1–2 sentence holistic assessment of the "
            "report's overall quality and eligibility, drawing on the check results and "
            "report content."
        ),
        user_message=user_message,
    )
    return output.summary, prompt_tokens, completion_tokens


def run_triage(
    checks: list[Check],
    report: Report,
    program: Program,
    model: str,
) -> ChecksResult:
    """Evaluate a policy's checks against a report via the plugin manager."""
    pm = create_plugin_manager(BuiltinChecks(model=model))

    results: list[CheckResult] = []
    total_prompt_tokens = 0
    total_completion_tokens = 0

    for check in checks:
        result = pm.hook.run_check(check=check, report=report, program=program)
        if result is None:
            raise NoiseGateError(
                f"No handler found for check '{check.id}'. "
                "Ensure a plugin is installed that handles this check ID."
            )
        results.append(result)
        total_prompt_tokens += result.prompt_tokens
        total_completion_tokens += result.completion_tokens

    summary, sp, sc = _run_summary(results, report, program, model)

    return ChecksResult(
        checks=results,
        summary=summary,
        verdict=derive_verdict(results, Policy(checks=checks)),
        model_used=model,
        prompt_tokens=total_prompt_tokens + sp,
        completion_tokens=total_completion_tokens + sc,
    )
