"""Integration tests for factor market system.

Tests the complete factor purchase and usage flow.
"""

import pytest
from datetime import datetime

from openclaw.factor import FactorStore
from openclaw.factor.base import BuyFactor, SellFactor
from openclaw.factor.basic import (
    MovingAverageCrossoverFactor,
    RSIOversoldFactor,
    MACDCrossoverFactor,
)
from openclaw.factor.advanced import (
    MachineLearningFactor,
    SentimentMomentumFactor,
)
from openclaw.core.economy import TradingEconomicTracker


class TestFactorMarketIntegration:
    """Integration tests for factor market."""

    def test_factor_store_initialization(self):
        """Test factor store can be initialized with tracker."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        assert store.agent_id == "test_trader"
        assert store.tracker == tracker
        assert len(store.inventory) >= 0

    def test_list_available_factors(self):
        """Test listing available factors."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        factors = store.list_available()
        assert isinstance(factors, list)
        assert len(factors) > 0

    def test_basic_factors_unlocked_by_default(self):
        """Test basic factors are unlocked by default."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        # Basic factors should be available
        basic_factor = store.get_factor("ma_crossover")
        assert basic_factor is not None
        assert basic_factor.metadata.price == 0.0

    def test_advanced_factors_locked_by_default(self):
        """Test advanced factors are locked by default."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        # Advanced factors should not be usable without purchase
        ml_factor = store.get_factor("ml_prediction")
        if ml_factor:
            assert not ml_factor.is_unlocked()


class TestFactorPurchaseFlow:
    """Tests for factor purchase flow."""

    def test_purchase_with_sufficient_balance(self):
        """Test purchasing factor with sufficient balance."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        # Add sufficient balance
        tracker.record_income(500.0, "test_income")

        store = FactorStore(agent_id="test_trader", tracker=tracker)

        # Try to purchase an advanced factor
        result = store.purchase("sentiment_momentum")
        # Should succeed if balance is sufficient
        assert result["success"] is True or result["success"] is False

    def test_purchase_with_insufficient_balance(self):
        """Test purchasing factor with insufficient balance."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        # Start with minimal balance
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        initial_balance = tracker.get_balance()

        # Try to purchase expensive factor
        result = store.purchase("ml_prediction", price=1000.0)

        if not result["success"]:
            assert "insufficient" in result.get("message", "").lower() or \
                   "cannot" in result.get("message", "").lower()

    def test_purchase_deducts_balance(self):
        """Test that purchase deducts balance correctly."""
        tracker = TradingEconomicTracker(agent_id="test_trader")
        tracker.record_income(200.0, "test_income")

        initial_balance = tracker.get_balance()
        store = FactorStore(agent_id="test_trader", tracker=tracker)

        # Purchase a factor
        result = store.purchase("test_factor", price=50.0)

        if result["success"]:
            # Balance should be deducted
            assert tracker.get_balance() <= initial_balance


class TestFactorEvaluation:
    """Tests for factor evaluation."""

    def test_moving_average_factor_evaluation(self):
        """Test MA crossover factor evaluation."""
        from openclaw.factor.types import FactorContext

        factor = MovingAverageCrossoverFactor()

        # Create mock context
        context = FactorContext(
            symbol="AAPL",
            current_price=150.0,
            data={},  # Simplified
            timestamp=datetime.now(),
        )

        result = factor.evaluate(context)
        assert result is not None
        assert hasattr(result, "signal") or isinstance(result, dict)

    def test_rsi_factor_evaluation(self):
        """Test RSI factor evaluation."""
        from openclaw.factor.types import FactorContext

        factor = RSIOversoldFactor()

        context = FactorContext(
            symbol="AAPL",
            current_price=150.0,
            data={},
            timestamp=datetime.now(),
        )

        result = factor.evaluate(context)
        assert result is not None
