import numpy as np

from fxhnt.application.forward_recompute import derive_nav, recompute_series


class _FakeStrategy:
    def __init__(self, series):
        self._series = series

    def advance(self, last_date, extra):
        return list(self._series), extra


def test_recompute_filters_to_since_t0():
    strat = _FakeStrategy([("2026-07-06", 0.01), ("2026-07-07", 0.02), ("2026-07-08", -0.01)])
    assert recompute_series(strat, "2026-07-07") == [("2026-07-07", 0.02), ("2026-07-08", -0.01)]


def test_recompute_is_deterministic():
    strat = _FakeStrategy([("2026-07-07", 0.02), ("2026-07-06", 0.01)])  # unsorted input
    a = recompute_series(strat, "2026-07-01")
    b = recompute_series(strat, "2026-07-01")
    assert a == b == [("2026-07-06", 0.01), ("2026-07-07", 0.02)]        # sorted, both runs identical


def test_derive_nav_matches_forward_tracker_formula():
    rows = [("2026-07-06", 0.01), ("2026-07-07", 0.02), ("2026-07-08", -0.01)]
    nav_rows, summary = derive_nav(rows)
    # nav compounds
    assert abs(nav_rows[-1][1] - (1.01 * 1.02 * 0.99)) < 1e-12
    assert summary["days"] == 3
    assert abs(summary["nav"] - 1.01 * 1.02 * 0.99) < 1e-12
    # sharpe uses per_period_sharpe * sqrt(365) for >=3 rows
    from fxhnt.domain.gauntlet import per_period_sharpe
    exp = float(per_period_sharpe(np.array([0.01, 0.02, -0.01])) * np.sqrt(365.0))
    assert abs(summary["sharpe"] - exp) < 1e-9


def test_derive_nav_empty_is_wait_safe():
    nav_rows, summary = derive_nav([])
    assert nav_rows == [] and summary["days"] == 0 and summary["nav"] == 1.0 and summary["last_date"] is None
