from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Dict, Optional
import pandas as pd


@dataclass
class StrategyResult:
    signal: str          # BUY / SELL / HOLD
    confidence: float    # 0.0 - 100.0
    metadata: dict = field(default_factory=dict)

    def to_dict(self) -> dict:
        return {
            "signal": self.signal,
            "confidence": self.confidence,
            "metadata": self.metadata,
        }


class BaseStrategy(ABC):
    """Abstract base class for all trading strategies."""

    def __init__(self, name: str, params: Optional[dict] = None):
        self.name = name
        self.params = params or {}

    @abstractmethod
    def analyze(self, data: Dict[str, pd.DataFrame]) -> StrategyResult:
        """
        Analyze market data across timeframes and return a trading signal.

        Args:
            data: dict mapping timeframe strings to OHLCV DataFrames.
                  E.g. {"15m": df_15m, "1h": df_1h}

        Returns:
            StrategyResult with signal, confidence, and metadata.
        """
        pass

    def get_name(self) -> str:
        return self.name

    def update_params(self, params: dict):
        """Hot-reload strategy parameters without restarting."""
        self.params.update(params)
