"""
Momentum Strategy - Trade in direction of strong price movements
"""
from typing import Optional
import pandas as pd
import numpy as np
from .base import BaseStrategy, Signal, SignalType


class MomentumStrategy(BaseStrategy):
    """
    Momentum Strategy

    Logic:
    - Identify strong momentum using ROC (Rate of Change)
    - Confirm with volume
    - Enter when momentum accelerates
    - Exit when momentum weakens

    Parameters:
    - roc_period: ROC period (default: 12)
    - roc_threshold: ROC threshold for signal (default: 2.0)
    - volume_sma: Volume SMA period (default: 20)
    - volume_multiplier: Volume multiplier threshold (default: 1.5)
    """

    def __init__(self, config: dict):
        super().__init__(config)
        self.roc_period = self.get_config_value('roc_period', 12)
        self.roc_threshold = self.get_config_value('roc_threshold', 2.0)
        self.volume_sma = self.get_config_value('volume_sma', 20)
        self.volume_multiplier = self.get_config_value('volume_multiplier', 1.5)

    def generate_signal(self, data: pd.DataFrame) -> Optional[Signal]:
        """
        Generate momentum signal

        Args:
            data: DataFrame with OHLCV data

        Returns:
            Signal object or None
        """
        min_periods = max(self.roc_period, self.volume_sma) + 5
        if len(data) < min_periods:
            self.logger.warning(f"Insufficient data: {len(data)} < {min_periods}")
            return None

        # Calculate indicators
        data = self._calculate_indicators(data)

        # Get latest values
        latest = data.iloc[-1]
        prev = data.iloc[-2]

        symbol = latest.get('symbol', 'UNKNOWN')
        current_price = latest['close']
        roc = latest['roc']
        prev_roc = prev['roc']
        volume_ratio = latest['volume_ratio']

        signal = None

        # Strong bullish momentum
        if roc > self.roc_threshold and volume_ratio > self.volume_multiplier:
            # Momentum accelerating
            if roc > prev_roc:
                signal = Signal(
                    symbol=symbol,
                    signal_type=SignalType.BUY,
                    confidence=self._calculate_confidence(roc, volume_ratio, 'buy'),
                    entry_price=current_price,
                    stop_loss=current_price * 0.97,  # 3% stop loss
                    take_profit=current_price * 1.06,  # 6% take profit
                    reason=f"Momentum BUY: ROC {roc:.2f}%, Volume {volume_ratio:.2f}x",
                    timestamp=latest.get('timestamp')
                )

        # Strong bearish momentum
        elif roc < -self.roc_threshold and volume_ratio > self.volume_multiplier:
            # Momentum accelerating
            if roc < prev_roc:
                signal = Signal(
                    symbol=symbol,
                    signal_type=SignalType.SELL,
                    confidence=self._calculate_confidence(-roc, volume_ratio, 'sell'),
                    entry_price=current_price,
                    stop_loss=current_price * 1.03,  # 3% stop loss
                    take_profit=current_price * 0.94,  # 6% take profit
                    reason=f"Momentum SELL: ROC {roc:.2f}%, Volume {volume_ratio:.2f}x",
                    timestamp=latest.get('timestamp')
                )

        # Momentum weakening - close positions
        elif abs(roc) < self.roc_threshold / 2:
            signal = Signal(
                symbol=symbol,
                signal_type=SignalType.CLOSE_LONG,
                confidence=0.7,
                entry_price=current_price,
                reason=f"Momentum weakening: ROC {roc:.2f}%",
                timestamp=latest.get('timestamp')
            )

        if signal:
            self.logger.info(f"Signal generated: {signal.reason}")

        return signal

    def _calculate_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
        """Calculate technical indicators"""
        df = data.copy()

        # Rate of Change (ROC)
        df['roc'] = ((df['close'] - df['close'].shift(self.roc_period)) / df['close'].shift(self.roc_period)) * 100

        # Volume ratio
        df['volume_sma'] = df['volume'].rolling(window=self.volume_sma).mean()
        df['volume_ratio'] = df['volume'] / df['volume_sma']

        return df

    def _calculate_confidence(
        self,
        roc: float,
        volume_ratio: float,
        direction: str
    ) -> float:
        """
        Calculate signal confidence based on momentum strength and volume

        Returns:
            Confidence score between 0.0 and 1.0
        """
        # ROC strength (normalized to 0-1)
        roc_strength = min(1.0, abs(roc) / 10.0)

        # Volume strength (normalized to 0-1)
        volume_strength = min(1.0, (volume_ratio - 1.0) / 2.0)

        # Combine metrics
        roc_weight = 0.6
        volume_weight = 0.4

        confidence = min(1.0, roc_strength * roc_weight + volume_strength * volume_weight)

        return confidence
