from __future__ import annotations

from historical_replay import Candle, ReplayResult, render_replay_report, run_replay_tournament
from strategy_registry import StrategyPreset


def _candle(i: int, close: float, high: float | None = None, low: float | None = None) -> Candle:
    return Candle(ts=1_700_000_000 + i * 60, open=close, high=high or close, low=low or close, close=close, volume=1_000_000)


def test_replay_opens_and_closes_flash_crash_rebound() -> None:
    preset = StrategyPreset(
        strategy_id="fast_rebound",
        label="Fast Rebound",
        source="unit",
        parameters={
            "flash_crash_trigger_pct": 4.5,
            "break_even_activation_pct": 0.4,
            "v_shape_activation_pct": 1.0,
            "v_shape_trail_dist_pct": 0.5,
            "dead_fish_time_limit_mins": 60,
            "atr_sl_multiplier": 1.5,
            "max_hard_stop_pct": 3.0,
            "trade_size_usd": 50.0,
            "default_leverage": 5,
            "min_volume_24h": 1,
        },
    )
    candles = {
        "BTC": [
            _candle(0, 100), _candle(1, 100), _candle(2, 100), _candle(3, 95),
            _candle(4, 96.5), _candle(5, 96.0),
        ]
    }

    results = run_replay_tournament([preset], candles, volumes={"BTC": 100_000_000})

    assert len(results) == 1
    result = results[0]
    assert isinstance(result, ReplayResult)
    assert result.strategy_id == "fast_rebound"
    assert result.closed_trades == 1
    assert result.total_pnl_usd > 0
    assert result.win_rate == 1.0
    assert result.trades[0].coin == "BTC"
    assert result.trades[0].exit_reason.startswith("V-Shape")


def test_replay_supports_squeeze_breakout_family() -> None:
    preset = StrategyPreset(
        strategy_id="squeeze",
        label="Squeeze",
        source="unit",
        parameters={
            "strategy_family": "volatility_squeeze_breakout",
            "squeeze_lookback_ticks": 4,
            "squeeze_max_band_width_pct": 1.2,
            "squeeze_breakout_pct": 0.4,
            "break_even_activation_pct": 0.2,
            "v_shape_activation_pct": 0.6,
            "v_shape_trail_dist_pct": 0.25,
            "dead_fish_time_limit_mins": 60,
            "atr_sl_multiplier": 1.0,
            "max_hard_stop_pct": 2.0,
            "trade_size_usd": 50.0,
            "min_volume_24h": 1,
        },
    )
    candles = {
        "SOL": [
            _candle(0, 100.00),
            _candle(1, 100.10),
            _candle(2, 99.95),
            _candle(3, 100.00),
            _candle(4, 100.60),
            _candle(5, 101.30),
            _candle(6, 101.00),
        ]
    }

    result = run_replay_tournament([preset], candles, volumes={"SOL": 99_000_000})[0]

    assert result.closed_trades == 1
    assert result.trades[0].coin == "SOL"
    assert result.total_pnl_usd > 0


def test_replay_ranks_multiple_presets_by_risk_adjusted_score() -> None:
    loose = StrategyPreset(
        strategy_id="loose",
        label="Loose",
        source="unit",
        parameters={"flash_crash_trigger_pct": 4.5, "max_hard_stop_pct": 10.0, "atr_sl_multiplier": 4.0, "dead_fish_time_limit_mins": 60, "trade_size_usd": 50.0, "min_volume_24h": 1},
    )
    tight = StrategyPreset(
        strategy_id="tight",
        label="Tight",
        source="unit",
        parameters={"flash_crash_trigger_pct": 4.5, "max_hard_stop_pct": 2.0, "dead_fish_time_limit_mins": 60, "trade_size_usd": 50.0, "min_volume_24h": 1},
    )
    candles = {
        "ETH": [_candle(0, 100), _candle(1, 100), _candle(2, 95), _candle(3, 90), _candle(4, 89)],
        "SOL": [_candle(0, 100), _candle(1, 100), _candle(2, 95), _candle(3, 97), _candle(4, 96.5)],
    }

    results = run_replay_tournament([loose, tight], candles, volumes={"ETH": 99_000_000, "SOL": 99_000_000})

    assert [r.strategy_id for r in results] == ["tight", "loose"]
    assert results[0].score > results[1].score


def test_render_replay_report_marks_small_samples() -> None:
    preset = StrategyPreset(strategy_id="empty", label="Empty", source="unit", parameters={})

    report = render_replay_report(run_replay_tournament([preset], {"BTC": [_candle(0, 100)]}, volumes={"BTC": 100_000_000}), min_samples=5)

    assert "Historical Replay Tournament" in report
    assert "empty" in report
    assert "observation-only" in report
