"""Grid trading strategy."""

from decimal import Decimal
from typing import Optional, Dict, Any, List
from src.strategies.base import BaseStrategy, StrategySignal, SignalType
from src.core.logger import get_logger

logger = get_logger(__name__)


class GridStrategy(BaseStrategy):
    """Grid trading strategy - buy at lower levels, sell at higher levels."""
    
    def __init__(self, name: str, parameters: Optional[Dict[str, Any]] = None, timeframes: Optional[list] = None):
        """Initialize Grid strategy.
        
        Parameters:
            grid_spacing: Percentage spacing between grid levels (default: 1%)
            num_levels: Number of grid levels above and below center (default: 10)
            center_price: Center price for grid (default: current price)
            profit_target: Profit target percentage (default: 2%)
        """
        super().__init__(name, parameters, timeframes)
        self.grid_spacing = Decimal(str(self.parameters.get('grid_spacing', 1))) / 100
        self.num_levels = self.parameters.get('num_levels', 10)
        self.center_price = self.parameters.get('center_price')
        self.profit_target = Decimal(str(self.parameters.get('profit_target', 2))) / 100
        
        # Grid levels
        self.buy_levels: List[Decimal] = []
        self.sell_levels: List[Decimal] = []
        self.positions: Dict[Decimal, Decimal] = {}  # entry_price -> quantity
    
    def _update_grid_levels(self, current_price: Decimal):
        """Update grid levels based on current price."""
        if not self.center_price:
            self.center_price = current_price
        
        # Calculate grid levels
        self.buy_levels = []
        self.sell_levels = []
        
        for i in range(1, self.num_levels + 1):
            # Buy levels below center
            buy_price = self.center_price * (1 - self.grid_spacing * Decimal(i))
            self.buy_levels.append(buy_price)
            
            # Sell levels above center
            sell_price = self.center_price * (1 + self.grid_spacing * Decimal(i))
            self.sell_levels.append(sell_price)
        
        # Sort levels
        self.buy_levels.sort(reverse=True)  # Highest to lowest
        self.sell_levels.sort()  # Lowest to highest
    
    async def on_tick(self, symbol: str, price: Decimal, timeframe: str, data: Dict[str, Any]) -> Optional[StrategySignal]:
        """Generate grid trading signals."""
        self._update_grid_levels(price)
        
        # Check buy levels
        for buy_level in self.buy_levels:
            if price <= buy_level and buy_level not in self.positions:
                # Buy signal
                quantity = self.parameters.get('position_size', Decimal('0.1'))
                return StrategySignal(
                    signal_type=SignalType.BUY,
                    symbol=symbol,
                    strength=0.8,
                    price=buy_level,
                    quantity=quantity,
                    metadata={
                        'grid_level': float(buy_level),
                        'strategy': 'grid',
                        'type': 'buy'
                    }
                )
        
        # Check sell levels (profit taking)
        for entry_price, quantity in list(self.positions.items()):
            profit_pct = (price - entry_price) / entry_price
            if profit_pct >= self.profit_target:
                # Sell signal for profit taking
                del self.positions[entry_price]
                return StrategySignal(
                    signal_type=SignalType.SELL,
                    symbol=symbol,
                    strength=1.0,
                    price=price,
                    quantity=quantity,
                    metadata={
                        'entry_price': float(entry_price),
                        'profit_pct': float(profit_pct * 100),
                        'strategy': 'grid',
                        'type': 'profit_take'
                    }
                )
        
        return None
    
    def on_signal(self, signal: StrategySignal) -> Optional[StrategySignal]:
        """Process signal and track positions."""
        if signal.signal_type == SignalType.BUY:
            # Track position
            self.positions[signal.price] = signal.quantity
        elif signal.signal_type == SignalType.SELL:
            # Position already removed in on_tick
            pass
        
        return signal if self.should_execute(signal) else None
