"""
BaseStrategy - Abstract base class for trading strategies
"""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional, List
from enum import Enum
import pandas as pd
import logging

logger = logging.getLogger(__name__)


class SignalType(Enum):
    """Trading signal types"""
    BUY = "buy"
    SELL = "sell"
    HOLD = "hold"
    CLOSE_LONG = "close_long"
    CLOSE_SHORT = "close_short"


@dataclass
class Signal:
    """Trading signal"""
    symbol: str
    signal_type: SignalType
    confidence: float  # 0.0 to 1.0
    entry_price: float
    stop_loss: Optional[float] = None
    take_profit: Optional[float] = None
    reason: str = ""
    timestamp: Optional[pd.Timestamp] = None


class BaseStrategy(ABC):
    """
    Abstract base class for trading strategies.
    All strategies must implement the generate_signal method.
    """

    def __init__(self, config: dict):
        self.config = config
        self.name = self.__class__.__name__
        self.logger = logging.getLogger(f"{__name__}.{self.name}")

    @abstractmethod
    def generate_signal(self, data: pd.DataFrame) -> Optional[Signal]:
        """
        Generate trading signal from market data

        Args:
            data: DataFrame with OHLCV data and indicators

        Returns:
            Signal object or None
        """
        pass

    def validate_data(self, data: pd.DataFrame, required_columns: List[str]) -> bool:
        """
        Validate that required columns exist in data

        Args:
            data: DataFrame to validate
            required_columns: List of required column names

        Returns:
            True if all columns exist, False otherwise
        """
        missing = [col for col in required_columns if col not in data.columns]
        if missing:
            self.logger.error(f"Missing required columns: {missing}")
            return False
        return True

    def get_config_value(self, key: str, default=None):
        """Get configuration value with default"""
        return self.config.get(key, default)

    def __repr__(self) -> str:
        return f"<{self.name}>"
