"""Tests for Intent analysis module."""

from __future__ import annotations

import polars as pl
from tradepose_client.analysis.trades.intent import (
    FullWorkflowReport,
    IntentReport,
    StepInsight,
    entry_timing,
    exit_placement,
    full_workflow,
    position_sizing,
    trailing_breakeven,
    volatility_stability,
)


class TestIntentReport:
    """Tests for IntentReport dataclass."""

    def test_intent_report_creation(self) -> None:
        """Test IntentReport creation."""
        report = IntentReport(
            intent_name="Test Intent",
            intent_description="Test description",
            stats={"key": "value"},
            insights=[
                StepInsight(
                    observation="Test observation",
                    recommendation="Test recommendation",
                    priority="high",
                )
            ],
        )

        assert report.intent_name == "Test Intent"
        assert report.intent_description == "Test description"
        assert report.stats == {"key": "value"}
        assert len(report.insights) == 1

    def test_intent_report_summary(self) -> None:
        """Test IntentReport summary method."""
        report = IntentReport(
            intent_name="Test Intent",
            intent_description="Test description",
            stats={"metric1": 1.234, "metric2": "text"},
            insights=[
                StepInsight(
                    observation="Something observed",
                    recommendation="Do this",
                    priority="high",
                    next_step="Go to next step",
                )
            ],
        )

        summary = report.summary()

        assert "Test Intent" in summary
        assert "Test description" in summary
        assert "metric1" in summary
        assert "1.234" in summary
        assert "Something observed" in summary
        assert "Do this" in summary
        assert "HIGH" in summary

    def test_intent_report_repr_html(self) -> None:
        """Test IntentReport HTML representation."""
        report = IntentReport(
            intent_name="Test Intent",
            intent_description="Test description",
            stats={"value": 1.0},
            insights=[
                StepInsight(
                    observation="Observed",
                    recommendation="Recommend",
                    priority="medium",
                )
            ],
        )

        html = report._repr_html_()

        assert "Test Intent" in html
        assert "Test description" in html
        assert "Observed" in html
        assert "Recommend" in html


class TestStepInsight:
    """Tests for StepInsight dataclass."""

    def test_step_insight_creation(self) -> None:
        """Test StepInsight creation."""
        insight = StepInsight(
            observation="MAE is stable",
            recommendation="Continue analysis",
            priority="low",
            next_step="Check MFE",
        )

        assert insight.observation == "MAE is stable"
        assert insight.recommendation == "Continue analysis"
        assert insight.priority == "low"
        assert insight.next_step == "Check MFE"

    def test_step_insight_without_next_step(self) -> None:
        """Test StepInsight without next_step."""
        insight = StepInsight(
            observation="Final observation",
            recommendation="Final recommendation",
            priority="high",
        )

        assert insight.next_step is None


class TestVolatilityStability:
    """Tests for volatility_stability intent."""

    def test_volatility_stability_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test volatility_stability with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = volatility_stability(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, IntentReport)
        assert report.intent_name == "A. Volatility Stability"
        assert "mae_mean" in report.stats or "error" in report.stats

    def test_volatility_stability_missing_columns(self) -> None:
        """Test volatility_stability with missing columns."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        # DataFrame without mae/mfe columns
        df = pl.DataFrame({"pnl": [100, -50, 200]})
        report = volatility_stability(df, DEFAULT_CONFIG)

        assert "error" in report.stats


class TestEntryTiming:
    """Tests for entry_timing intent."""

    def test_entry_timing_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test entry_timing with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = entry_timing(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, IntentReport)
        assert report.intent_name == "B. Entry Timing"


class TestExitPlacement:
    """Tests for exit_placement intent."""

    def test_exit_placement_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test exit_placement with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = exit_placement(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, IntentReport)
        assert report.intent_name == "C. Exit Placement"


class TestTrailingBreakeven:
    """Tests for trailing_breakeven intent."""

    def test_trailing_breakeven_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test trailing_breakeven with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = trailing_breakeven(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, IntentReport)
        assert report.intent_name == "D. Trailing & Breakeven"


class TestPositionSizing:
    """Tests for position_sizing intent."""

    def test_position_sizing_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test position_sizing with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = position_sizing(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, IntentReport)
        assert report.intent_name == "E. Position Sizing"


class TestFullWorkflow:
    """Tests for full_workflow intent."""

    def test_full_workflow_basic(self, sample_trades_df: pl.DataFrame) -> None:
        """Test full_workflow with basic data."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = full_workflow(sample_trades_df, DEFAULT_CONFIG)

        assert isinstance(report, FullWorkflowReport)
        assert report.n_trades == len(sample_trades_df)
        assert isinstance(report.step_a, IntentReport)
        assert isinstance(report.step_b, IntentReport)
        assert isinstance(report.step_c, IntentReport)
        assert isinstance(report.step_d, IntentReport)
        assert isinstance(report.step_e, IntentReport)

    def test_full_workflow_summary(self, sample_trades_df: pl.DataFrame) -> None:
        """Test FullWorkflowReport summary method."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = full_workflow(sample_trades_df, DEFAULT_CONFIG)
        summary = report.summary()

        assert "MAE/MFE 5-Step Workflow Analysis" in summary
        assert "A. Volatility Stability" in summary
        assert "B. Entry Timing" in summary
        assert "C. Exit Placement" in summary
        assert "D. Trailing & Breakeven" in summary
        assert "E. Position Sizing" in summary


class TestNormalizationAndBins:
    """Tests for normalization mode and bins parameter."""

    def test_volatility_stability_normalized(self, sample_trades_df: pl.DataFrame) -> None:
        """Test volatility_stability with normalize=True."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        # Add volatility columns if not present
        if "mae_volatility" not in sample_trades_df.columns:
            sample_trades_df = sample_trades_df.with_columns(
                [
                    pl.lit(1.0).alias("mae_volatility"),
                    pl.lit(1.0).alias("mfe_volatility"),
                ]
            )

        report = volatility_stability(sample_trades_df, DEFAULT_CONFIG, normalize=True)
        assert isinstance(report, IntentReport)
        assert report.intent_name == "A. Volatility Stability"

    def test_entry_timing_custom_bins(self, sample_trades_df: pl.DataFrame) -> None:
        """Test entry_timing with custom bins parameter."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        report = entry_timing(sample_trades_df, DEFAULT_CONFIG, bins=50)
        assert isinstance(report, IntentReport)
        assert report.intent_name == "B. Entry Timing"

    def test_exit_placement_both_params(self, sample_trades_df: pl.DataFrame) -> None:
        """Test exit_placement with both normalize and bins."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        # Add volatility columns
        if "mae_volatility" not in sample_trades_df.columns:
            sample_trades_df = sample_trades_df.with_columns(
                [
                    pl.lit(1.0).alias("mae_volatility"),
                    pl.lit(1.0).alias("mfe_volatility"),
                ]
            )

        report = exit_placement(sample_trades_df, DEFAULT_CONFIG, normalize=True, bins=40)
        assert isinstance(report, IntentReport)
        assert report.intent_name == "C. Exit Placement"

    def test_full_workflow_with_params(self, sample_trades_df: pl.DataFrame) -> None:
        """Test full_workflow with normalize and bins."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        # Add volatility columns
        if "mae_volatility" not in sample_trades_df.columns:
            sample_trades_df = sample_trades_df.with_columns(
                [
                    pl.lit(1.0).alias("mae_volatility"),
                    pl.lit(1.0).alias("mfe_volatility"),
                ]
            )

        report = full_workflow(sample_trades_df, DEFAULT_CONFIG, normalize=True, bins=25)
        assert isinstance(report, FullWorkflowReport)
        assert report.n_trades == len(sample_trades_df)

    def test_normalize_filters_null_volatility(self, sample_trades_df: pl.DataFrame) -> None:
        """Test that normalize=True filters out rows with null volatility."""
        from tradepose_client.analysis.mae_mfe.config import DEFAULT_CONFIG

        # Add volatility columns with some null values
        n = len(sample_trades_df)
        volatility_values = [1.0] * (n - 2) + [None, None]  # Last 2 are null
        sample_trades_df = sample_trades_df.with_columns(
            [
                pl.Series("mae_volatility", volatility_values),
                pl.Series("mfe_volatility", volatility_values),
            ]
        )

        report = volatility_stability(sample_trades_df, DEFAULT_CONFIG, normalize=True)

        # Should have filtered count in stats
        assert "normalize_filtered" in report.stats
        assert report.stats["normalize_filtered"] == 2
        assert report.stats["normalize_original"] == n
