"""refresh_nav_summary: MATERIALIZE the bybit headline nav-summary (stats + pre-rendered curve) from the
persisted paper_nav series, keyed by the nav's latest run_date (the version). The stored payload must be
byte-for-byte identical to the live `_overview_headline` compute (same `nav_backfill_stats` + `nav_sparkline`
helpers). In-memory SQLite — no network, no Postgres."""
from __future__ import annotations

import datetime as dt

from fxhnt.adapters.persistence.paper_repo import PaperRepo
from fxhnt.adapters.web.charts import nav_sparkline
from fxhnt.application.nav_stats import nav_backfill_stats
from fxhnt.application.nav_summary import refresh_nav_summary

_AT = dt.datetime(2026, 6, 24, 12, 0)
_PTS = [100_000.0, 140_000.0, 120_000.0, 210_000.0, 300_000.0, 360_000.0, 393_955.0]


def _seeded_repo(pts: list[float] = _PTS) -> PaperRepo:
    repo = PaperRepo("sqlite://")
    repo.migrate()
    for i, eq in enumerate(pts):
        rd = dt.date(2021, 1, 1) + dt.timedelta(days=120 * i)
        repo.upsert_nav(rd.isoformat(), capital=100_000.0, realized=0.0, unrealized=0.0, equity=eq, at=_AT)
    return repo


def test_refresh_matches_live_stats_and_curve() -> None:
    repo = _seeded_repo()
    payload = refresh_nav_summary(repo)

    # Live compute via the EXACT helpers _overview_headline uses, on the same nav.
    nav = repo.nav_history()
    equities = [p.equity for p in nav]
    stats = nav_backfill_stats(equities)
    assert payload["final_equity"] == stats.final_equity
    assert payload["total_return_pct"] == stats.total_return_pct
    assert payload["sharpe"] == stats.sharpe
    assert payload["max_dd_pct"] == stats.max_dd_pct
    assert payload["curve_svg"] == nav_sparkline(equities, width=600, height=160)
    assert payload["since"] == "2021"
    assert payload["has_record"] is True
    assert payload["nav_run_date"] == nav[-1].run_date


def test_read_back_equals_written_payload() -> None:
    repo = _seeded_repo()
    written = refresh_nav_summary(repo)
    read = repo.read_nav_summary()
    assert read is not None
    for k in ("nav_run_date", "final_equity", "total_return_pct", "sharpe", "max_dd_pct",
              "since", "has_record", "curve_svg"):
        assert read[k] == written[k], k


def test_version_is_latest_run_date_and_goes_stale_on_new_nav() -> None:
    repo = _seeded_repo()
    refresh_nav_summary(repo)
    # Fresh: stored version == the live latest run_date.
    assert repo.read_nav_summary()["nav_run_date"] == repo.latest_nav_run_date()
    # A new nav day → the stored summary is now stale (its version no longer matches).
    repo.upsert_nav("2024-01-01", capital=100_000.0, realized=0.0, unrealized=0.0, equity=420_000.0, at=_AT)
    assert repo.read_nav_summary()["nav_run_date"] != repo.latest_nav_run_date()
    # Re-refresh re-matches and picks up the new final equity.
    refresh_nav_summary(repo)
    assert repo.read_nav_summary()["nav_run_date"] == repo.latest_nav_run_date()
    assert repo.read_nav_summary()["final_equity"] == 420_000.0


def test_empty_nav_is_zeroed_summary() -> None:
    repo = PaperRepo("sqlite://")
    repo.migrate()
    payload = refresh_nav_summary(repo)
    assert payload["nav_run_date"] == ""
    assert payload["since"] == ""
    assert payload["has_record"] is False
    assert payload["curve_svg"] == ""
    assert payload["final_equity"] == 0.0


def test_missing_summary_reads_none() -> None:
    repo = _seeded_repo()
    assert repo.read_nav_summary() is None   # nothing stored until refresh runs
