"""Momentum trading strategy."""

from decimal import Decimal
from typing import Optional, Dict, Any, List
import pandas as pd
from src.strategies.base import BaseStrategy, StrategySignal, SignalType
from src.data.indicators import get_indicators
from src.core.logger import get_logger

logger = get_logger(__name__)


class MomentumStrategy(BaseStrategy):
    """Momentum-based trading strategy."""
    
    def __init__(self, name: str, parameters: Optional[Dict[str, Any]] = None, timeframes: Optional[list] = None):
        """Initialize Momentum strategy.
        
        Parameters:
            lookback_period: Lookback period for momentum calculation (default: 20)
            momentum_threshold: Minimum momentum strength to enter (default: 0.05 = 5%)
            volume_threshold: Minimum volume increase for confirmation (default: 1.5x)
            exit_threshold: Momentum reversal threshold for exit (default: -0.02 = -2%)
        """
        super().__init__(name, parameters, timeframes)
        self.lookback_period = self.parameters.get('lookback_period', 20)
        self.momentum_threshold = Decimal(str(self.parameters.get('momentum_threshold', 0.05)))
        self.volume_threshold = self.parameters.get('volume_threshold', 1.5)
        self.exit_threshold = Decimal(str(self.parameters.get('exit_threshold', -0.02)))
        
        self.indicators = get_indicators()
        self._price_history: List[float] = []
        self._volume_history: List[float] = []
        self._in_position = False
        self._entry_price: Optional[Decimal] = None
    
    def _calculate_momentum(self, prices: pd.Series) -> float:
        """Calculate price momentum.
        
        Args:
            prices: Series of prices
            
        Returns:
            Momentum value (percentage change)
        """
        if len(prices) < self.lookback_period:
            return 0.0
        
        recent_prices = prices[-self.lookback_period:]
        old_price = recent_prices.iloc[0]
        new_price = recent_prices.iloc[-1]
        
        if old_price == 0:
            return 0.0
        
        return float((new_price - old_price) / old_price)
    
    def _check_volume_confirmation(self, volumes: pd.Series) -> bool:
        """Check if volume confirms momentum.
        
        Args:
            volumes: Series of volumes
            
        Returns:
            True if volume confirms
        """
        if len(volumes) < self.lookback_period:
            return False
        
        recent_volumes = volumes[-self.lookback_period:]
        avg_volume = recent_volumes.mean()
        current_volume = recent_volumes.iloc[-1]
        
        return current_volume >= avg_volume * self.volume_threshold
    
    async def on_tick(self, symbol: str, price: Decimal, timeframe: str, data: Dict[str, Any]) -> Optional[StrategySignal]:
        """Generate momentum-based signals."""
        # Add to history
        self._price_history.append(float(price))
        self._volume_history.append(float(data.get('volume', 0)))
        
        if len(self._price_history) < self.lookback_period + 1:
            return None
        
        prices = pd.Series(self._price_history)
        volumes = pd.Series(self._volume_history)
        
        # Calculate momentum
        momentum = self._calculate_momentum(prices)
        
        if not self._in_position:
            # Entry logic
            if momentum >= float(self.momentum_threshold):
                # Check volume confirmation
                if self._check_volume_confirmation(volumes):
                    self._in_position = True
                    self._entry_price = price
                    
                    return StrategySignal(
                        signal_type=SignalType.BUY,
                        symbol=symbol,
                        strength=min(momentum / float(self.momentum_threshold), 1.0),
                        price=price,
                        metadata={
                            'momentum': momentum,
                            'volume_confirmed': True,
                            'strategy': 'momentum',
                            'type': 'entry'
                        }
                    )
        else:
            # Exit logic
            if momentum <= float(self.exit_threshold):
                self._in_position = False
                entry_price = self._entry_price or price
                
                return StrategySignal(
                    signal_type=SignalType.SELL,
                    symbol=symbol,
                    strength=1.0,
                    price=price,
                    metadata={
                        'momentum': momentum,
                        'entry_price': float(entry_price),
                        'strategy': 'momentum',
                        'type': 'exit'
                    }
                )
        
        return None
    
    def on_signal(self, signal: StrategySignal) -> Optional[StrategySignal]:
        """Process signal."""
        if signal.signal_type == SignalType.SELL:
            self._in_position = False
            self._entry_price = None
        
        return signal if self.should_execute(signal) else None
