"""Dollar Cost Averaging (DCA) strategy."""

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

logger = get_logger(__name__)


class DCAStrategy(BaseStrategy):
    """Dollar Cost Averaging strategy - fixed amount per interval."""
    
    def __init__(self, name: str, parameters: Optional[Dict[str, Any]] = None, timeframes: Optional[list] = None):
        """Initialize DCA strategy.
        
        Parameters:
            amount: Fixed amount to invest per interval (default: 10)
            interval: Interval type - 'daily', 'weekly', 'monthly' (default: 'daily')
            target_allocation: Target allocation percentage (default: 10%)
        """
        super().__init__(name, parameters, timeframes)
        self.amount = Decimal(str(self.parameters.get('amount', 10)))
        self.interval = self.parameters.get('interval', 'daily')
        self.target_allocation = Decimal(str(self.parameters.get('target_allocation', 10))) / 100
        
        # Track last purchase
        self.last_purchase_time: Optional[datetime] = None
        self._calculate_interval_delta()
    
    def _calculate_interval_delta(self):
        """Calculate timedelta for interval."""
        if self.interval == 'daily':
            self.interval_delta = timedelta(days=1)
        elif self.interval == 'weekly':
            self.interval_delta = timedelta(weeks=1)
        elif self.interval == 'monthly':
            self.interval_delta = timedelta(days=30)
        else:
            self.interval_delta = timedelta(days=1)
    
    async def on_tick(self, symbol: str, price: Decimal, timeframe: str, data: Dict[str, Any]) -> Optional[StrategySignal]:
        """Generate DCA signal based on interval."""
        now = datetime.utcnow()
        
        # Check if enough time has passed since last purchase
        if self.last_purchase_time:
            time_since_last = now - self.last_purchase_time
            if time_since_last < self.interval_delta:
                return None
        
        # Generate buy signal for fixed amount
        quantity = self.amount / price
        
        self.last_purchase_time = now
        
        return StrategySignal(
            signal_type=SignalType.BUY,
            symbol=symbol,
            strength=1.0,
            price=price,
            quantity=quantity,
            metadata={
                'amount': float(self.amount),
                'interval': self.interval,
                'strategy': 'dca'
            }
        )
    
    def on_signal(self, signal: StrategySignal) -> Optional[StrategySignal]:
        """Process signal."""
        return signal if self.should_execute(signal) else None
    
    def should_rebalance(self, current_allocation: Decimal, portfolio_value: Decimal) -> bool:
        """Check if rebalancing is needed.
        
        Args:
            current_allocation: Current allocation percentage
            portfolio_value: Total portfolio value
            
        Returns:
            True if rebalancing needed
        """
        target_value = portfolio_value * self.target_allocation
        current_value = portfolio_value * current_allocation
        
        # Rebalance if allocation deviates by more than 5%
        deviation = abs(current_allocation - self.target_allocation)
        return deviation > Decimal('0.05')
