"""
Nova Agent - Aggressive trading agent
Profile: Aggressive (10%+ monthly target, 20% max drawdown)
"""
from typing import Optional
import logging
from .base import BaseAgent, AgentConfig, RiskProfile, Position
from ..strategies.momentum import MomentumStrategy
from ..strategies.trend_following import TrendFollowingStrategy
from ..execution.risk_manager import RiskManager, RiskConfig

logger = logging.getLogger(__name__)


class NovaAgent(BaseAgent):
    """
    Nova - The Star (Aggressive Agent)

    Profile:
    - Risk: Aggressive
    - Target: 10%+ monthly
    - Max Drawdown: 20%
    - Pairs: All available pairs
    - Strategies: Momentum, Scalping, Trend Following
    - Max Positions: 10
    - Trades/day: 20+
    """

    def __init__(self, equity: float = 1000.0):
        # Create configuration
        config = AgentConfig(
            name="Nova",
            profile=RiskProfile.AGGRESSIVE,
            max_drawdown=20.0,
            position_size_pct=20.0,  # 20% of equity per position
            max_positions=10,
            allowed_pairs=[
                # Major pairs
                "BTCUSDT", "ETHUSDT", "BNBUSDT",
                # Top altcoins
                "ADAUSDT", "DOGEUSDT", "XRPUSDT", "DOTUSDT", "SOLUSDT",
                "MATICUSDT", "LINKUSDT", "AVAXUSDT", "UNIUSDT", "LTCUSDT",
                # High volatility altcoins
                "ATOMUSDT", "ETCUSDT", "FILUSDT", "TRXUSDT", "XLMUSDT",
                "VETUSDT", "ICPUSDT", "FTMUSDT", "SANDUSDT", "MANAUSDT"
            ],
            strategies=["momentum", "trend_following", "scalping"],
            max_trades_per_day=50,
            min_equity=100.0,
            stop_loss_pct=4.0,
            take_profit_pct=8.0
        )

        super().__init__(config)

        # Initialize equity
        self.update_equity(equity)

        # Initialize risk manager
        risk_config = RiskConfig(
            max_drawdown=config.max_drawdown,
            max_positions=config.max_positions,
            position_size_pct=config.position_size_pct,
            max_position_size_pct=25.0,
            min_position_size_usd=10.0,
            max_risk_per_trade=3.0,
            max_leverage=1.0
        )
        self.risk_manager = RiskManager(risk_config)

        # Initialize strategies
        self.momentum = MomentumStrategy({
            'roc_period': 10,
            'roc_threshold': 3.0,
            'volume_sma': 15,
            'volume_multiplier': 1.8
        })

        self.trend_following = TrendFollowingStrategy({
            'fast_ema': 8,
            'slow_ema': 21,
            'signal_ema': 5,
            'atr_period': 10,
            'atr_multiplier': 2.5
        })

        self.logger.info(f"Nova agent initialized with equity: ${equity:.2f}")

    async def on_start(self):
        """Called when agent starts"""
        self.logger.info(f"Nova agent starting - Equity: ${self.equity:.2f}")

    async def on_stop(self):
        """Called when agent stops"""
        self.logger.info(f"Nova agent stopping - Final equity: ${self.equity:.2f}")

        # Close all open positions
        if self.positions:
            self.logger.warning(f"Closing {len(self.positions)} open positions")

    async def on_signal(self, signal: dict):
        """
        Process trading signal from ML Engine

        Args:
            signal: Dict with keys like symbol, action, confidence, price, etc.
        """
        symbol = signal.get('symbol')
        action = signal.get('action', '').lower()
        confidence = signal.get('confidence', 0.0)
        price = signal.get('price', 0.0)

        # Validate symbol
        if symbol not in self.config.allowed_pairs:
            self.logger.debug(f"Symbol {symbol} not in allowed pairs")
            return

        # Evaluate if we should act on this signal
        should_enter = await self.evaluate_entry(signal)

        if not should_enter:
            return

        # Execute action
        if action == 'buy':
            await self._execute_buy(symbol, price, confidence)
        elif action == 'sell':
            await self._execute_sell(symbol, price, confidence)
        elif action == 'close':
            await self._execute_close(symbol)

    async def evaluate_entry(self, signal: dict) -> bool:
        """
        Evaluate if signal should be executed

        Args:
            signal: Trading signal

        Returns:
            True if signal should be executed
        """
        symbol = signal.get('symbol')
        confidence = signal.get('confidence', 0.0)

        # Check if agent can open position
        if not self.can_open_position():
            return False

        # Nova is aggressive - accept lower confidence signals
        if confidence < 0.50:
            self.logger.debug(f"Signal confidence too low: {confidence:.2f} < 0.50")
            return False

        # Check if we already have a position in this symbol
        existing_position = self.get_position(symbol)
        if existing_position:
            self.logger.debug(f"Already have position in {symbol}")
            return False

        # Check risk limits
        if not await self.check_risk_limits():
            return False

        return True

    async def _execute_buy(self, symbol: str, price: float, confidence: float):
        """Execute buy order"""
        self.logger.info(f"Executing BUY for {symbol} at {price:.2f} (confidence: {confidence:.2f})")

        # Calculate position size (more aggressive sizing)
        stop_loss = self.risk_manager.calculate_stop_loss(
            price, 'buy', self.config.stop_loss_pct
        )
        position_size = self.risk_manager.calculate_position_size(
            self.equity, price, stop_loss, risk_per_trade_pct=3.0
        )

        # Validate position
        is_valid, error = self.risk_manager.validate_position(
            symbol, 'buy', position_size, price, self.equity
        )

        if not is_valid:
            self.logger.error(f"Invalid position: {error}")
            return

        # Calculate take profit
        take_profit = self.risk_manager.calculate_take_profit(
            price, 'buy', self.config.take_profit_pct
        )

        # Create position
        position = Position(
            symbol=symbol,
            side='buy',
            quantity=position_size,
            entry_price=price,
            current_price=price,
            stop_loss=stop_loss,
            take_profit=take_profit
        )

        # Add position to agent
        self.add_position(position)

        self.logger.info(
            f"Position opened: {symbol} BUY {position_size:.6f} @ {price:.2f} "
            f"(SL: {stop_loss:.2f}, TP: {take_profit:.2f})"
        )

    async def _execute_sell(self, symbol: str, price: float, confidence: float):
        """Execute sell order (short)"""
        self.logger.info(f"Executing SELL for {symbol} at {price:.2f} (confidence: {confidence:.2f})")

        # Calculate position size
        stop_loss = self.risk_manager.calculate_stop_loss(
            price, 'sell', self.config.stop_loss_pct
        )
        position_size = self.risk_manager.calculate_position_size(
            self.equity, price, stop_loss, risk_per_trade_pct=3.0
        )

        # Validate position
        is_valid, error = self.risk_manager.validate_position(
            symbol, 'sell', position_size, price, self.equity
        )

        if not is_valid:
            self.logger.error(f"Invalid position: {error}")
            return

        # Calculate take profit
        take_profit = self.risk_manager.calculate_take_profit(
            price, 'sell', self.config.take_profit_pct
        )

        # Create position
        position = Position(
            symbol=symbol,
            side='sell',
            quantity=position_size,
            entry_price=price,
            current_price=price,
            stop_loss=stop_loss,
            take_profit=take_profit
        )

        # Add position to agent
        self.add_position(position)

        self.logger.info(
            f"Position opened: {symbol} SELL {position_size:.6f} @ {price:.2f} "
            f"(SL: {stop_loss:.2f}, TP: {take_profit:.2f})"
        )

    async def _execute_close(self, symbol: str):
        """Close position for symbol"""
        position = self.get_position(symbol)

        if not position:
            self.logger.warning(f"No position found for {symbol}")
            return

        # Calculate PnL
        position.update_pnl(position.current_price)

        # Remove position
        self.remove_position(symbol)

        # Record trade
        self.record_trade(position.pnl)

        # Update equity
        new_equity = self.equity + position.pnl
        self.update_equity(new_equity)

        self.logger.info(
            f"Position closed: {symbol} PnL: ${position.pnl:.2f} ({position.pnl_percent:.2f}%)"
        )

    async def update_positions(self, market_prices: dict):
        """
        Update all positions with current market prices

        Args:
            market_prices: Dict mapping symbol to current price
        """
        for position in self.positions:
            current_price = market_prices.get(position.symbol)

            if current_price:
                position.update_pnl(current_price)

                # Check if stop loss or take profit hit
                should_close, reason = self.risk_manager.should_close_position(
                    position.entry_price,
                    current_price,
                    position.side,
                    position.stop_loss,
                    position.take_profit
                )

                if should_close:
                    self.logger.info(f"Closing {position.symbol} - Reason: {reason}")
                    await self._execute_close(position.symbol)
