"""Unit Tests for Backtesting Engine & Performance Metrics."""
from __future__ import annotations

import unittest

from backend.app.backtesting.engine import BacktestEngine
from backend.app.backtesting.metrics import calculate_performance_metrics
from backend.app.backtesting.walk_forward import WalkForwardValidator
from backend.app.market_data.mock_client import MockBybitClient


class TestBacktestEngine(unittest.TestCase):
    def setUp(self) -> None:
        self.mock_client = MockBybitClient()
        self.candles = self.mock_client.get_klines("BTCUSDT", "15m", 150)
        self.engine = BacktestEngine(initial_equity=10000.0)

    def test_performance_metrics_calculation(self) -> None:
        """Verify performance metrics math."""
        initial = 10000.0
        equity_curve = [10000.0, 10100.0, 10050.0, 10250.0]
        pnls = [100.0, -50.0, 200.0]
        fees = [2.0, 2.0, 2.0]

        report = calculate_performance_metrics(initial, equity_curve, pnls, fees, benchmark_buy_and_hold_return=2.0)
        self.assertEqual(report.total_trades, 3)
        self.assertEqual(report.winning_trades, 2)
        self.assertEqual(report.losing_trades, 1)
        self.assertEqual(report.win_rate_pct, 66.67)
        self.assertEqual(report.net_pnl, 250.0)
        self.assertGreater(report.profit_factor, 1.0)
        self.assertGreater(report.total_fees, 0.0)

    def test_backtest_run_simulation(self) -> None:
        """Verify backtest execution produces auditable trade ledger and equity curve."""
        report, trades, equity_curve = self.engine.run(self.candles)
        self.assertIsNotNone(report)
        self.assertEqual(len(equity_curve), len(self.candles) - 35 + 1)
        for t in trades:
            self.assertGreater(t.fee_paid, 0.0)
            self.assertIn(t.exit_reason, ["STOP_LOSS", "TAKE_PROFIT", "END_OF_DATA"])

    def test_walk_forward_validation_execution(self) -> None:
        """Verify walk-forward validator evaluates out-of-sample segments without crashing."""
        validator = WalkForwardValidator(train_bars=50, val_bars=20, test_bars=20, embargo_bars=2)
        res = validator.run_validation(self.candles)
        self.assertGreaterEqual(res["windows_evaluated"], 1)


if __name__ == "__main__":
    unittest.main()
