"""Version history tab — list, diff, save, restore."""

from __future__ import annotations

import streamlit as st

from app.utils import icon

from app.views._helpers import safe
from core.tei_client import TEIClient


def _flatten_values(values: list[dict]) -> dict[str, dict]:
    """Index a values list by field_key for easy diffing."""
    return {v.get("field_key", ""): v for v in values}


def _diff_rows(a: dict[str, dict], b: dict[str, dict]) -> list[dict]:
    """Return one row per field with side-by-side year values."""
    keys = sorted(set(a.keys()) | set(b.keys()))
    rows: list[dict] = []

    def _years_of(v: dict) -> dict:
        """Accept both friendly (year_values) and wire (nested years) shapes."""
        if isinstance(v.get("year_values"), dict):
            return {str(k): val for k, val in v["year_values"].items()}
        if isinstance(v.get("years"), dict):
            return {
                str(k): (cell or {}).get("value")
                for k, cell in v["years"].items()
            }
        if v.get("value") is not None:
            return {"1": v["value"]}
        return {}

    for k in keys:
        av = a.get(k, {}) or {}
        bv = b.get(k, {}) or {}
        ay = _years_of(av)
        by = _years_of(bv)
        years = sorted(set(ay.keys()) | set(by.keys()), key=lambda x: int(x))
        for y in years:
            a_val = float(ay.get(y) or 0)
            b_val = float(by.get(y) or 0)
            if abs(a_val - b_val) < 1e-9:
                continue
            rows.append(
                {
                    "field_key": k,
                    "year": y,
                    "left": a_val,
                    "right": b_val,
                    "delta": b_val - a_val,
                }
            )
    return rows


def render(client: TEIClient, tool: dict) -> None:
    st.markdown(
        f"<h2>{icon('clock-history')} Versions</h2>",
        unsafe_allow_html=True,
    )
    public_id = tool["id"]

    versions = safe(client.list_versions, public_id) or []
    versions = sorted(
        versions, key=lambda v: int(v.get("version_number") or 0), reverse=True
    )

    # Save new version
    with st.expander("Save current state as a new version", expanded=not versions):
        note = st.text_area(
            "Version note",
            placeholder=(
                "What changed? E.g. 'CFO confirmed 1.8M contacts/month; "
                "raised legacy license cost from $160 to $180/agent.'"
            ),
        )
        if st.button("Save version", disabled=not note.strip()):
            result = safe(client.save_version, public_id, note.strip())
            if result:
                st.success(
                    f"Saved version {result.get('version_number', '?')}."
                )
                st.rerun()

    if not versions:
        st.info("No versions saved yet.")
        return

    # Listing
    st.subheader("History")
    rows = []
    for v in versions:
        snap = v.get("summary_snapshot") or v.get("summary") or {}
        rows.append(
            {
                "Version": v.get("version_number"),
                "Date": v.get("created_at") or v.get("date"),
                "NPV": float(snap.get("net_present_value") or snap.get("npv") or 0),
                "ROI %": float(
                    snap.get("roi_percentage")
                    or snap.get("roi")
                    or snap.get("roi_pct")
                    or 0
                ),
                "Note": v.get("note", ""),
            }
        )
    st.dataframe(rows, width="stretch", hide_index=True)


    # Compare two versions
    st.subheader("Compare")
    if len(versions) < 2:
        st.caption("Save two or more versions to compare.")
        return
    labels = {f"v{v['version_number']} — {v.get('note', '')[:40]}": v for v in versions}
    keys = list(labels.keys())
    c1, c2 = st.columns(2)
    with c1:
        left_label = st.selectbox("Left (older)", keys, index=min(1, len(keys) - 1))
    with c2:
        right_label = st.selectbox("Right (newer)", keys, index=0)

    if left_label == right_label:
        st.caption("Pick two different versions to see a diff.")
        return

    left = safe(client.get_version, public_id, labels[left_label]["version_number"])
    right = safe(client.get_version, public_id, labels[right_label]["version_number"])
    if not (left and right):
        return

    a_values = left.get("values_snapshot") or left.get("values") or []
    b_values = right.get("values_snapshot") or right.get("values") or []
    diff = _diff_rows(_flatten_values(a_values), _flatten_values(b_values))
    if not diff:
        st.success("No value differences between these versions.")
    else:
        st.dataframe(diff, width="stretch", hide_index=True)

