"""Pure record-derivation for the deterministic forward engine (spec sub-project A).

`recompute_series` realises the recompute-from-anchor primitive: a recompute-mode strategy's full-history
series (`advance(None, {})`) filtered to dates on/after the frozen T0. `derive_nav` projects any (date, ret)
series into the nav/summary the cockpit + gate read, using the SAME formulae as the legacy
`ForwardTracker.step` so the migration reconciles byte-for-byte."""
from __future__ import annotations

from typing import Any

import numpy as np

from fxhnt.application.forward_tracker import ForwardStrategy
from fxhnt.domain.gauntlet import per_period_sharpe

_ANN = np.sqrt(365.0)


def recompute_series(strategy: ForwardStrategy, t0: str) -> list[tuple[str, float]]:
    """Return strategy's full-history series sorted and filtered to dates >= t0.

    Args:
        strategy: A ForwardStrategy whose advance() method returns full history when last_date=None.
        t0: ISO-date string to filter from (inclusive).

    Returns:
        List of (date_str, return_float) tuples sorted by date, date >= t0 only.
    """
    rows, _ = strategy.advance(None, {})
    rows = sorted(((str(d), float(r)) for d, r in rows), key=lambda x: x[0])
    return [(d, r) for d, r in rows if d >= t0]


def derive_nav(rows: list[tuple[str, float]]) -> tuple[list[tuple[str, float]], dict[str, Any]]:
    """Project (date, return) series into (nav_rows, summary) using ForwardTracker.step formulae.

    Args:
        rows: List of (date_str, return_float) tuples.

    Returns:
        (nav_rows, summary) where:
        - nav_rows: [(date, nav)] with nav compounded (1 -> 1*(1+r1)*(1+r2)...).
        - summary: {"days", "nav", "total_return", "sharpe", "maxdd", "last_date"}.
                   sharpe = per_period_sharpe * sqrt(365) when >=3 rows else 0.
                   maxdd = peak-to-trough max drawdown.
                   For empty rows: days=0, nav=1.0, last_date=None.
    """
    nav = 1.0
    nav_rows: list[tuple[str, float]] = []
    rets: list[float] = []
    for d, r in rows:
        nav *= (1.0 + r)
        nav_rows.append((d, nav))
        rets.append(r)
    if not rows:
        return [], {
            "days": 0,
            "nav": 1.0,
            "total_return": 0.0,
            "sharpe": 0.0,
            "maxdd": 0.0,
            "last_date": None,
        }
    arr = np.array(rets)
    navs = np.array([n for _, n in nav_rows])
    sharpe = float(per_period_sharpe(arr) * _ANN) if len(arr) >= 3 else 0.0
    maxdd = float((navs / np.maximum.accumulate(navs) - 1.0).min())
    return nav_rows, {
        "days": len(rows),
        "nav": nav,
        "total_return": nav - 1.0,
        "sharpe": sharpe,
        "maxdd": maxdd,
        "last_date": rows[-1][0],
    }
