"""
Pandas dataframe builders for benefit / cost / summary tables.

Each builder accepts the friendly value-row dicts returned by
``core.tei_client.TEIClient.get_values`` and returns a
nicely-formatted DataFrame for display in notebooks.
"""

from __future__ import annotations

from collections.abc import Iterable
from typing import Any

import pandas as pd

from core.calculations import risk_adjust_benefit, risk_adjust_cost


def _years_in_data(items: Iterable[dict]) -> list[int]:
    years: set[int] = set()
    for it in items:
        for k in (it.get("year_values") or {}):
            try:
                years.add(int(k))
            except (TypeError, ValueError):
                continue
    return sorted(years)


def benefits_table(items: list[dict]) -> pd.DataFrame:
    """Tidy benefits dataframe with one row per benefit, year columns, totals."""
    if not items:
        return pd.DataFrame(
            columns=["field_key", "label", "category", "risk_adjustment"]
        )
    years = _years_in_data(items)
    rows: list[dict[str, Any]] = []
    for it in items:
        rf = float(it.get("risk_adjustment") or 0.0)
        yv = it.get("year_values") or {}
        row = {
            "field_key": it.get("field_key", ""),
            "label": it.get("label", "") or it.get("field_key", ""),
            "category": it.get("category", ""),
            "risk_adjustment": rf,
        }
        nominal_total = 0.0
        ra_total = 0.0
        for y in years:
            v = float(yv.get(str(y)) or 0.0)
            ra = risk_adjust_benefit(v, rf)
            row[f"Year {y}"] = v
            row[f"Year {y} (RA)"] = ra
            nominal_total += v
            ra_total += ra
        row["Total"] = nominal_total
        row["Total (RA)"] = ra_total
        rows.append(row)
    return pd.DataFrame(rows)


def costs_table(items: list[dict]) -> pd.DataFrame:
    """Tidy costs dataframe — adds an Initial column when present."""
    if not items:
        return pd.DataFrame(
            columns=["field_key", "label", "category", "risk_adjustment", "Initial"]
        )
    years = _years_in_data(items)
    rows: list[dict[str, Any]] = []
    for it in items:
        rf = float(it.get("risk_adjustment") or 0.0)
        yv = it.get("year_values") or {}
        initial = float(it.get("initial") or 0.0)
        row = {
            "field_key": it.get("field_key", ""),
            "label": it.get("label", "") or it.get("field_key", ""),
            "category": it.get("category", ""),
            "risk_adjustment": rf,
            "Initial": initial,
            "Initial (RA)": risk_adjust_cost(initial, rf),
        }
        nominal_total = initial
        ra_total = risk_adjust_cost(initial, rf)
        for y in years:
            v = float(yv.get(str(y)) or 0.0)
            ra = risk_adjust_cost(v, rf)
            row[f"Year {y}"] = v
            row[f"Year {y} (RA)"] = ra
            nominal_total += v
            ra_total += ra
        row["Total"] = nominal_total
        row["Total (RA)"] = ra_total
        rows.append(row)
    return pd.DataFrame(rows)


def summary_table(summary: dict) -> pd.DataFrame:
    """Single-row summary dataframe of headline KPIs."""
    pb = summary.get("payback_months")
    pb_str = f"{float(pb):.1f} months" if pb not in (None, "") else "N/A"
    data = {
        "NPV": [float(summary.get("npv") or 0)],
        "ROI %": [float(summary.get("roi") or summary.get("roi_pct") or 0)],
        "Payback": [pb_str],
        "Benefits PV": [float(summary.get("total_benefits_pv") or 0)],
        "Costs PV": [float(summary.get("total_costs_pv") or 0)],
        "Discount rate": [float(summary.get("discount_rate") or 0)],
        "Analysis years": [int(summary.get("analysis_years") or 0)],
    }
    return pd.DataFrame(data)


def cashflow_table(summary: dict) -> pd.DataFrame:
    """Per-year cashflow dataframe from a summary's ``yearly_breakdown``."""
    yb = summary.get("yearly_breakdown") or []
    if not yb:
        return pd.DataFrame(columns=["Year", "Benefits", "Costs", "Net", "Cumulative"])
    df = pd.DataFrame(yb)
    rename = {
        "year": "Year",
        "benefits": "Benefits",
        "costs": "Costs",
        "net": "Net",
        "cumulative_net": "Cumulative",
    }
    df = df.rename(columns=rename)
    return df
