"""Tests for parameter optimization functionality."""

from __future__ import annotations

import pytest
from tradepose_client.analysis.trades.optimization import (
    OptimalExitParameters,
    calculate_optimal_parameters,
)


class TestCalculateOptimalParameters:
    """Test optimal parameter calculation."""

    def test_calculate_basic_parameters(self, sample_trades_df):
        """Test basic parameter calculation."""
        params = calculate_optimal_parameters(sample_trades_df)

        assert isinstance(params, OptimalExitParameters)
        assert params.sample_size == len(sample_trades_df)

    def test_stop_loss_parameters(self, sample_trades_df):
        """Test stop loss parameter calculation."""
        params = calculate_optimal_parameters(sample_trades_df)

        # SL parameters should be positive
        assert params.sl_p50_raw > 0
        assert params.sl_p75_raw > 0
        # P75 should be >= P50
        assert params.sl_p75_raw >= params.sl_p50_raw

        # ATR-normalized values should exist when volatility columns present
        assert params.sl_p50_atr is not None
        assert params.sl_p75_atr is not None

    def test_take_profit_parameters(self, sample_trades_df):
        """Test take profit parameter calculation."""
        params = calculate_optimal_parameters(sample_trades_df)

        # TP parameters should be positive
        assert params.tp_p50_raw > 0
        assert params.tp_p75_raw > 0
        # P75 should be >= P50
        assert params.tp_p75_raw >= params.tp_p50_raw

    def test_trailing_stop_parameters(self, sample_trades_df):
        """Test trailing stop parameter calculation."""
        params = calculate_optimal_parameters(sample_trades_df)

        # Trailing parameters should be positive
        assert params.trailing_activation_raw >= 0
        assert params.trailing_distance_raw >= 0

    def test_timeout_parameter(self, sample_trades_df):
        """Test timeout parameter calculation."""
        params = calculate_optimal_parameters(sample_trades_df)

        # Timeout should be a positive integer
        assert params.optimal_timeout_bars > 0
        assert isinstance(params.optimal_timeout_bars, int)

    def test_hit_rates(self, sample_trades_df):
        """Test hit rate calculations."""
        params = calculate_optimal_parameters(sample_trades_df)

        # Hit rates should be between 0 and 1
        assert 0 <= params.sl_hit_rate <= 1
        assert 0 <= params.tp_hit_rate <= 1

    def test_empty_dataframe_error(self, empty_trades_df):
        """Test error on empty DataFrame."""
        with pytest.raises(ValueError, match="empty DataFrame"):
            calculate_optimal_parameters(empty_trades_df)

    def test_minimal_dataframe(self, minimal_trades_df):
        """Test with minimal columns (no MAE/MFE)."""
        params = calculate_optimal_parameters(minimal_trades_df)

        # Should handle missing MAE/MFE gracefully
        assert params.sample_size == len(minimal_trades_df)
        # SL/TP will be 0 when MAE/MFE columns missing
        assert params.sl_p50_raw == 0.0
        assert params.tp_p50_raw == 0.0

    def test_summary_string(self, sample_trades_df):
        """Test summary string generation."""
        params = calculate_optimal_parameters(sample_trades_df)
        summary = params.summary()

        assert "Optimal Exit Parameters" in summary
        assert "Stop Loss" in summary
        assert "Take Profit" in summary
        assert "Trailing Stop" in summary
        assert "Timeout" in summary


class TestOptimalExitParametersDataclass:
    """Test OptimalExitParameters dataclass."""

    def test_all_fields_present(self, sample_trades_df):
        """Test that all expected fields are present."""
        params = calculate_optimal_parameters(sample_trades_df)

        # Check all required fields exist
        assert hasattr(params, "sl_p50_raw")
        assert hasattr(params, "sl_p75_raw")
        assert hasattr(params, "sl_p50_atr")
        assert hasattr(params, "sl_p75_atr")
        assert hasattr(params, "tp_p50_raw")
        assert hasattr(params, "tp_p75_raw")
        assert hasattr(params, "tp_p50_atr")
        assert hasattr(params, "tp_p75_atr")
        assert hasattr(params, "trailing_activation_raw")
        assert hasattr(params, "trailing_distance_raw")
        assert hasattr(params, "breakeven_activation_raw")
        assert hasattr(params, "optimal_timeout_bars")
        assert hasattr(params, "sample_size")
        assert hasattr(params, "sl_hit_rate")
        assert hasattr(params, "tp_hit_rate")
