"""nav_backfill_stats — comparable, deterministic summary metrics from a persisted NAV EQUITY series.

The bybit deploy book has a multi-year BACKFILL persisted in paper_nav (the equity curve ending ~$393,955).
This pure helper turns that equity series into the headline figures the Overview leads with — total return,
annualised Sharpe (mean daily simple-return / population-std × √365, the repo convention), worst peak-to-
trough drawdown, and the final equity — so the page shows the REAL record instead of a not-started 0.00.

Pure: no DB, no network, no clock. The web layer reads the nav series via PaperRepo and passes the equities
in; everything here is arithmetic on that list."""
from __future__ import annotations

import math
import statistics as st
from dataclasses import dataclass

# Annualisation factor for crypto (trades 365 days/yr) — the SAME constant the bybit sleeve metrics use,
# so the headline Sharpe is on one consistent basis with the rest of the cockpit.
_PERIODS_PER_YEAR = 365


@dataclass(frozen=True, slots=True)
class BackfillStats:
    """Headline summary of a backfilled NAV equity series. All percentages are in PERCENT (e.g. +293.96),
    max_dd_pct is NEGATIVE (a drawdown), sharpe is annualised (≈ daily Sharpe × √365)."""
    final_equity: float
    total_return_pct: float
    sharpe: float
    max_dd_pct: float


def nav_backfill_stats(nav: list[float]) -> BackfillStats:
    """Summarise a NAV equity series (ascending by date). Empty/singleton → all-zero (final = last point if
    present). Sharpe is mean/pstdev × √365 of the daily SIMPLE returns; max_dd is the worst running peak-to-
    trough of the equity itself; total return is last/first − 1. Deterministic, no side effects."""
    if not nav:
        return BackfillStats(final_equity=0.0, total_return_pct=0.0, sharpe=0.0, max_dd_pct=0.0)
    final = nav[-1]
    if len(nav) < 2:
        return BackfillStats(final_equity=final, total_return_pct=0.0, sharpe=0.0, max_dd_pct=0.0)

    first = nav[0]
    total_return_pct = (final / first - 1.0) * 100.0 if first > 0 else 0.0

    rets = [nav[i] / nav[i - 1] - 1.0 for i in range(1, len(nav)) if nav[i - 1] > 0]
    sharpe = 0.0
    if len(rets) >= 2:
        sd = st.pstdev(rets)
        if sd > 0:
            sharpe = st.mean(rets) / sd * math.sqrt(_PERIODS_PER_YEAR)

    peak = nav[0]
    max_dd = 0.0
    for v in nav:
        peak = max(peak, v)
        if peak > 0:
            max_dd = min(max_dd, v / peak - 1.0)

    return BackfillStats(final_equity=final, total_return_pct=total_return_pct, sharpe=sharpe,
                         max_dd_pct=max_dd * 100.0)
