"""Tests for DataSource declaration in StrategyBuilder."""

import polars as pl
import pytest
from tradepose_client.builder import BlueprintBuilder, StrategyBuilder
from tradepose_models.enums import Freq, IndicatorType
from tradepose_models.strategy import DataSource


def _minimal_base_bp():
    """Create a minimal base blueprint for build() tests."""
    return (
        BlueprintBuilder("base", "Long", "Trend")
        .add_entry_trigger(
            name="entry",
            conditions=[],
            offset_expr=pl.lit(0.0),
            order_strategy="ImmediateEntry",
            priority=1,
        )
        .build()
    )


class TestAddDataSource:
    def test_add_data_source_basic(self):
        builder = StrategyBuilder("test", "US100", "15min")
        result = builder.add_data_source("XAUUSD", "1h")
        assert result is builder
        assert len(builder._data_sources) == 1
        assert builder._data_sources[0].instrument == "XAUUSD"
        assert builder._data_sources[0].freq == Freq.HOUR_1

    def test_duplicate_data_source_raises(self):
        builder = StrategyBuilder("test", "US100", "15min")
        builder.add_data_source("XAUUSD", Freq.HOUR_1)
        with pytest.raises(ValueError, match="already declared"):
            builder.add_data_source("XAUUSD", Freq.MIN_15)

    def test_data_source_is_base_instrument_raises(self):
        builder = StrategyBuilder("test", "US100", "15min")
        with pytest.raises(ValueError, match="base_instrument"):
            builder.add_data_source("US100", "1h")

    def test_build_includes_data_sources(self):
        builder = StrategyBuilder("test", "US100", "15min")
        builder.add_data_source("XAUUSD", Freq.MIN_15)
        builder.set_base_blueprint(_minimal_base_bp())

        config = builder.build()
        assert len(config.data_sources) == 1
        assert config.data_sources[0].instrument == "XAUUSD"
        assert config.data_sources[0].freq == Freq.MIN_15


class TestCrossInstrumentIndicator:
    def test_add_indicator_without_data_source_raises(self):
        builder = StrategyBuilder("test", "US100", "15min")
        with pytest.raises(ValueError, match="requires a data source declaration"):
            builder.add_indicator(
                IndicatorType.ATR,
                freq=Freq.HOUR_1,
                instrument="XAUUSD",
                period=14,
            )

    def test_add_cross_instrument_indicator_with_data_source(self):
        builder = StrategyBuilder("test", "US100", "15min")
        builder.add_data_source("XAUUSD", Freq.MIN_15)
        spec = builder.add_indicator(
            IndicatorType.ATR,
            freq=Freq.HOUR_1,
            instrument="XAUUSD",
            period=14,
        )
        assert spec.instrument == "XAUUSD"
        assert spec.freq == Freq.HOUR_1

    def test_add_indicator_freq_below_data_source_raises(self):
        builder = StrategyBuilder("test", "US100", "15min")
        builder.add_data_source("XAUUSD", Freq.HOUR_1)
        with pytest.raises(ValueError, match="lower than data source freq"):
            builder.add_indicator(
                IndicatorType.ATR,
                freq=Freq.MIN_15,
                instrument="XAUUSD",
                period=14,
            )


class TestBackwardCompat:
    def test_no_data_sources_normal_build(self):
        builder = StrategyBuilder("test", "US100", "15min")
        builder.add_indicator(IndicatorType.ATR, freq=Freq.DAY_1, period=14)
        builder.set_base_blueprint(_minimal_base_bp())
        config = builder.build()
        assert config.data_sources == []
        assert len(config.indicators) == 1


class TestDataSourceModel:
    def test_serialization_roundtrip(self):
        ds = DataSource(instrument="XAUUSD", freq=Freq.HOUR_1)
        data = ds.model_dump()
        restored = DataSource.model_validate(data)
        assert restored.instrument == "XAUUSD"
        assert restored.freq == Freq.HOUR_1
        assert restored.instrument_id is None

    def test_json_roundtrip(self):
        ds = DataSource(instrument="XAUUSD", instrument_id=42, freq=Freq.MIN_15)
        json_str = ds.model_dump_json()
        restored = DataSource.model_validate_json(json_str)
        assert restored.instrument == "XAUUSD"
        assert restored.instrument_id == 42
        assert restored.freq == Freq.MIN_15
