from __future__ import annotations

import datetime as dt

import pytest

from apps.backtester.run import BacktestRunner
from libs.backtest.domain import BacktestConfig


def _runner(initial_equity: float, fixed_capital_sizing: bool) -> BacktestRunner:
    runner = BacktestRunner.__new__(BacktestRunner)
    runner.initial_equity = initial_equity
    runner._fixed_capital_sizing = fixed_capital_sizing
    runner.config = BacktestConfig(strategy_name="test", dataset_snapshot_id="snap")
    runner.config.risk.buying_power_multiplier = 1.0
    return runner


def test_fixed_capital_buying_power_caps_gains_at_initial_equity() -> None:
    runner = _runner(initial_equity=100_000.0, fixed_capital_sizing=True)

    assert runner._compute_buying_power(equity=150_000.0, gross_exposure=90_000.0) == pytest.approx(10_000.0)


def test_fixed_capital_buying_power_does_not_create_leverage_after_drawdown() -> None:
    runner = _runner(initial_equity=100_000.0, fixed_capital_sizing=True)

    assert runner._compute_buying_power(equity=80_000.0, gross_exposure=90_000.0) == pytest.approx(0.0)


def test_fixed_capital_sleeve_equity_caps_gains_but_respects_drawdown() -> None:
    runner = _runner(initial_equity=100_000.0, fixed_capital_sizing=True)
    runner._compute_positions_market_value = lambda _date: 30_000.0
    runner._get_parking_value = lambda _date: 20_000.0

    runner._cash = 80_000.0
    assert runner._sleeve_equity_est(dt.date(2026, 1, 5)) == pytest.approx(100_000.0)

    runner._cash = 40_000.0
    assert runner._sleeve_equity_est(dt.date(2026, 1, 5)) == pytest.approx(90_000.0)
