"""Position sizing rules."""

from decimal import Decimal
from typing import Optional
from src.core.config import get_config
from src.core.logger import get_logger
from src.exchanges.base import BaseExchangeAdapter

logger = get_logger(__name__)


class PositionSizingManager:
    """Manages position sizing calculations."""
    
    def __init__(self):
        """Initialize position sizing manager."""
        self.config = get_config()
        self.logger = get_logger(__name__)
    
    def calculate_size(
        self,
        symbol: str,
        price: Decimal,
        balance: Decimal,
        risk_percent: Optional[Decimal] = None,
        exchange_adapter: Optional[BaseExchangeAdapter] = None
    ) -> Decimal:
        """Calculate position size, accounting for fees.
        
        Args:
            symbol: Trading symbol
            price: Entry price
            balance: Available balance
            risk_percent: Risk percentage (uses config default if None)
            exchange_adapter: Exchange adapter for fee calculation (optional)
            
        Returns:
            Calculated position size
        """
        if risk_percent is None:
            risk_percent = Decimal(str(
                self.config.get("risk.position_size_percent", 2.0)
            )) / 100
        
        position_value = balance * risk_percent
        
        # Account for fees by reserving fee amount
        from src.trading.fee_calculator import get_fee_calculator
        fee_calculator = get_fee_calculator()
        
        # Reserve ~0.4% for round-trip fees
        fee_reserve = fee_calculator.calculate_fee_reserve(
            position_value=position_value,
            exchange_adapter=exchange_adapter,
            reserve_percent=0.004  # 0.4% for round-trip
        )
        
        # Adjust position value to account for fees
        adjusted_position_value = position_value - fee_reserve
        
        if price > 0:
            quantity = adjusted_position_value / price
            return max(Decimal(0), quantity)  # Ensure non-negative
        
        return Decimal(0)
    
    def calculate_kelly_criterion(
        self,
        win_rate: float,
        avg_win: float,
        avg_loss: float
    ) -> Decimal:
        """Calculate position size using Kelly Criterion.
        
        Args:
            win_rate: Win rate (0.0 to 1.0)
            avg_win: Average win amount
            avg_loss: Average loss amount
            
        Returns:
            Kelly percentage
        """
        if avg_loss == 0:
            return Decimal(0)
        
        kelly = (win_rate * avg_win - (1 - win_rate) * avg_loss) / avg_win
        # Use fractional Kelly (half) for safety
        return Decimal(str(kelly / 2))
    
    def validate_position_size(
        self,
        symbol: str,
        quantity: Decimal,
        price: Decimal,
        balance: Decimal,
        exchange_adapter: Optional[BaseExchangeAdapter] = None
    ) -> bool:
        """Validate position size against limits, accounting for fees.
        
        Args:
            symbol: Trading symbol
            quantity: Position quantity
            price: Entry price
            balance: Available balance
            exchange_adapter: Exchange adapter for fee calculation (optional)
            
        Returns:
            True if position size is valid
        """
        position_value = quantity * price
        
        # Calculate estimated fee for this trade
        from src.trading.fee_calculator import get_fee_calculator
        from src.core.database import OrderType
        
        fee_calculator = get_fee_calculator()
        estimated_fee = fee_calculator.calculate_fee(
            quantity=quantity,
            price=price,
            order_type=OrderType.MARKET,  # Use market as worst case
            exchange_adapter=exchange_adapter
        )
        
        total_cost = position_value + estimated_fee
        
        # Check if exceeds available balance (including fees)
        if total_cost > balance:
            self.logger.warning(
                f"Position cost {total_cost} (value: {position_value}, fee: {estimated_fee}) "
                f"exceeds balance {balance}"
            )
            return False
        
        # Check against risk limits
        max_position_percent = Decimal(str(
            self.config.get("risk.position_size_percent", 2.0)
        )) / 100
        
        if position_value > balance * max_position_percent:
            self.logger.warning(f"Position size exceeds risk limit")
            return False
        
        return True

