"""Tests for base strategy class."""

import pytest
import pandas as pd
from src.strategies.base import BaseStrategy, StrategyRegistry


class ConcreteStrategy(BaseStrategy):
    """Concrete strategy for testing."""
    
    async def on_data(self, new_data: pd.DataFrame):
        """Handle new data."""
        self.current_data = pd.concat([self.current_data, new_data]).tail(100)
    
    async def generate_signal(self):
        """Generate signal."""
        if len(self.current_data) > 0:
            return {"signal": "hold", "price": self.current_data['close'].iloc[-1]}
        return {"signal": "hold", "price": None}
    
    async def calculate_position_size(self, capital: float, risk_percentage: float) -> float:
        """Calculate position size."""
        return capital * risk_percentage


class TestBaseStrategy:
    """Tests for BaseStrategy."""
    
    @pytest.fixture
    def strategy(self):
        """Create strategy instance."""
        return ConcreteStrategy(
            strategy_id=1,
            name="test_strategy",
            symbol="BTC/USD",
            timeframe="1h",
            parameters={}
        )
    
    def test_strategy_initialization(self, strategy):
        """Test strategy initialization."""
        assert strategy.strategy_id == 1
        assert strategy.name == "test_strategy"
        assert strategy.symbol == "BTC/USD"
        assert strategy.timeframe == "1h"
        assert not strategy.is_active
    
    @pytest.mark.asyncio
    async def test_strategy_start_stop(self, strategy):
        """Test strategy start and stop."""
        await strategy.start()
        assert strategy.is_active
        
        await strategy.stop()
        assert not strategy.is_active
    
    @pytest.mark.asyncio
    async def test_generate_signal(self, strategy):
        """Test signal generation."""
        signal = await strategy.generate_signal()
        assert "signal" in signal
        assert signal["signal"] in ["buy", "sell", "hold"]
    
    @pytest.mark.asyncio
    async def test_calculate_position_size(self, strategy):
        """Test position size calculation."""
        size = await strategy.calculate_position_size(1000.0, 0.01)
        assert size == 10.0


class TestStrategyRegistry:
    """Tests for StrategyRegistry."""
    
    def test_register_strategy(self):
        """Test strategy registration."""
        StrategyRegistry.register_strategy("test_strategy", ConcreteStrategy)
        assert "test_strategy" in StrategyRegistry.list_available()
    
    def test_get_strategy_class(self):
        """Test getting strategy class."""
        StrategyRegistry.register_strategy("test_strategy", ConcreteStrategy)
        strategy_class = StrategyRegistry.get_strategy_class("test_strategy")
        assert strategy_class == ConcreteStrategy
    
    def test_get_nonexistent_strategy(self):
        """Test getting non-existent strategy."""
        with pytest.raises(ValueError, match="not registered"):
            StrategyRegistry.get_strategy_class("nonexistent")

