"""Confidence scoring, grounding checks, abstain rules."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from app.fdi.compute import ComputedResult


@dataclass
class VerifiedAnswer:
    text: str
    confidence: float
    abstain: bool = False
    citations: list[dict[str, Any]] = field(default_factory=list)
    evidence: dict[str, Any] = field(default_factory=dict)


def score_confidence(
    *,
    parse_confidence: float = 0.7,
    tool_fit: float = 0.8,
    result_confidence: float = 0.8,
    verifier_pass: float = 1.0,
) -> float:
    return round(
        0.30 * parse_confidence
        + 0.25 * tool_fit
        + 0.25 * result_confidence
        + 0.20 * verifier_pass,
        3,
    )


def format_money(value: float | None, currency: str | None = "INR") -> str:
    if value is None:
        return "n/a"
    cur = "₹" if (currency or "").upper() in {"INR", "RS", "₹"} else (currency or "")
    return f"{cur} {value:,.2f}".strip()


def render_computed(result: ComputedResult) -> VerifiedAnswer:
    if not result.ok:
        return VerifiedAnswer(
            text=result.message or "I couldn't find that in the structured index.",
            confidence=result.confidence or 0.7,
            abstain=True,
            evidence={"metric": result.metric, "ok": False},
        )

    citations = [{"id": eid, "kind": "fdi"} for eid in result.evidence_ids[:8]]
    conf = score_confidence(result_confidence=result.confidence or 0.8)

    if result.metric == "identifier":
        lines = [result.message]
        for row in result.group_rows[:10]:
            lines.append(
                f"- {row.get('id_type')}: {row.get('value_raw')} "
                f"(from {row.get('filename')}, type={row.get('doc_type')})"
            )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    if result.metric == "inventory":
        lines = [f"Your knowledge base has {result.row_count} indexed financial document(s):"]
        for row in result.group_rows[:20]:
            lines.append(
                f"- {row.get('filename')} [{row.get('doc_type')}] "
                f"pages={row.get('page_count')} holder={row.get('holder_name') or '—'}"
            )
        return VerifiedAnswer("\n".join(lines), 1.0, False, citations, {"result": result.group_rows})

    if result.metric == "profile":
        rows = result.group_rows
        if len(rows) == 1:
            r = rows[0]
            text = (
                f"From your knowledge base, “{r.get('filename')}” is classified as "
                f"**{r.get('doc_type')}**. "
                + (f"Holder/party: {r.get('holder_name')}. " if r.get("holder_name") else "")
                + (f"Issuer: {r.get('issuer_name')}. " if r.get("issuer_name") else "")
                + (
                    f"Period: {r.get('period_start')} – {r.get('period_end')}. "
                    if r.get("period_start")
                    else ""
                )
            ).strip()
        else:
            text = f"You have {len(rows)} indexed documents. Ask about a specific file or metric."
        return VerifiedAnswer(text, conf, False, citations, {"result": rows})

    if result.metric == "group_counterparty":
        lines = [result.message + ":"]
        for row in result.group_rows[:10]:
            lines.append(
                f"- {row.get('name')}: {format_money(float(row.get('total') or 0))} "
                f"({row.get('n')} lines)"
            )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    if result.metric == "compare":
        lines = [result.message + ":"]
        for row in result.group_rows[:15]:
            metric = row.get("primary_metric")
            kind = row.get("primary_kind") or "metric"
            lines.append(
                f"- {row.get('filename')} [{row.get('doc_type')}] "
                f"{kind}={format_money(float(metric), 'INR') if metric is not None else '—'} "
                f"lines={row.get('line_count')}"
            )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    if result.metric == "reconcile":
        lines = [result.message]
        for row in result.group_rows[:20]:
            if row.get("status") == "matched":
                lines.append(
                    f"- Matched {format_money(float(row.get('invoice_amount') or 0))} "
                    f"({row.get('invoice')}) → {row.get('payment')} on {row.get('payment_date')}"
                )
            else:
                lines.append(
                    f"- Unmatched invoice {row.get('invoice')}: "
                    f"{format_money(float(row.get('invoice_amount') or 0))}"
                )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    if result.metric == "timeline":
        lines = [result.message + ":"]
        for row in result.group_rows[:20]:
            lines.append(
                f"- {row.get('event_date')}: {row.get('description_norm')} "
                f"{row.get('direction')} {format_money(float(row.get('amt') or 0))}"
            )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    if result.metric == "duplicates":
        if not result.group_rows:
            return VerifiedAnswer("No obvious duplicate amount/date groups found.", conf, False, citations, {})
        lines = [result.message + ":"]
        for row in result.group_rows[:15]:
            lines.append(
                f"- {row.get('event_date')}: {format_money(float(row.get('amt') or 0))} "
                f"×{row.get('n')} ({row.get('sample_desc')})"
            )
        return VerifiedAnswer("\n".join(lines), conf, False, citations, {"result": result.group_rows})

    # Scalar metrics
    if result.value is not None:
        text = (
            f"{result.message}: **{format_money(result.value, result.currency)}**"
            + (f" across {result.row_count} line items." if result.row_count else ".")
        )
        if result.group_rows and result.group_rows[0].get("source"):
            src = result.group_rows[0].get("source")
            text += f" Source: {src}."
        return VerifiedAnswer(text, conf, False, citations, {"value": result.value, "metric": result.metric})

    return VerifiedAnswer(result.message or "Done.", conf, False, citations, {})


def should_abstain(confidence: float, *, min_confidence: float = 0.5) -> bool:
    return confidence < min_confidence
