"""
Strategy execution tool wrapper for Agent
"""

import logging
from typing import Dict, Any

from openfund_agent.tools.base import BaseTool, register_tool
from openfund_agent.strategy.execution import StrategyExecutionTool

logger = logging.getLogger(__name__)


@register_tool
class StrategyExecutionToolWrapper(BaseTool):
    """
    Tool wrapper for strategy execution functionality

    This class wraps the StrategyExecutionTool to provide a standardized
    interface for the Agent to execute trading strategies.
    """

    def __init__(
        self,
        maker_config: Dict[str, Any],
        taker_config: Dict[str, Any],
        exchange_client: Any,
    ):
        """
        Initialize strategy execution tool wrapper

        Args:
            maker_config: Configuration for Openfund-maker
            taker_config: Configuration for Openfund-taker
            exchange_client: Exchange client instance
        """
        super().__init__(
            name="strategy_execution",
            description="Execute trading strategies and manage positions",
        )

        self.executor = StrategyExecutionTool(
            maker_config=maker_config,
            taker_config=taker_config,
            exchange_client=exchange_client,
        )

        logger.info("StrategyExecutionToolWrapper initialized")

    def _define_parameters(self) -> Dict[str, Any]:
        """
        Define parameter schema for strategy execution

        Returns:
            Parameter schema dictionary
        """
        return {
            "action": {
                "type": str,
                "required": True,
                "enum": ["generate_signals", "manage_positions", "execute_strategy"],
                "description": "Action type to perform",
            },
            "strategy_name": {
                "type": str,
                "required": True,
                "description": "Name of the strategy to execute",
            },
            "symbol": {
                "type": str,
                "required": False,
                "description": "Trading pair symbol (e.g., 'BTC/USDT:USDT')",
            },
            "market_data": {
                "type": dict,
                "required": False,
                "description": "Market data for signal generation",
            },
            "positions": {
                "type": list,
                "required": False,
                "description": "List of current positions for management",
            },
            "parameters": {
                "type": dict,
                "required": False,
                "description": "Strategy parameters and configuration",
            },
        }

    def execute(self, parameters: Dict[str, Any]) -> Any:
        """
        Execute the strategy tool with given parameters

        Args:
            parameters: Tool parameters including action, strategy_name, etc.

        Returns:
            Execution result based on the action type

        Raises:
            ValueError: If action is invalid or required parameters are missing
        """
        action = parameters.get("action")
        strategy_name = parameters.get("strategy_name")

        if not action:
            raise ValueError("action parameter is required")

        if not strategy_name:
            raise ValueError("strategy_name parameter is required")

        logger.info(f"Executing strategy tool action: {action} for {strategy_name}")

        try:
            if action == "generate_signals":
                return self._generate_signals(parameters)
            elif action == "manage_positions":
                return self._manage_positions(parameters)
            elif action == "execute_strategy":
                return self._execute_strategy(parameters)
            else:
                raise ValueError(f"Invalid action: {action}")

        except Exception as e:
            logger.error(f"Strategy tool execution failed: {str(e)}")
            raise

    def _generate_signals(self, parameters: Dict[str, Any]) -> Any:
        """
        Generate trading signals

        Args:
            parameters: Parameters including strategy_name and market_data

        Returns:
            List of trading signals
        """
        strategy_name = parameters["strategy_name"]
        market_data = parameters.get("market_data", {})

        if not market_data:
            raise ValueError("market_data is required for signal generation")

        logger.info(f"Generating signals for {strategy_name}")

        signals = self.executor.generate_signals(
            strategy_name=strategy_name, market_data=market_data
        )

        return {
            "success": True,
            "signals": [
                {
                    "symbol": sig.symbol,
                    "side": sig.side,
                    "entry_price": sig.entry_price,
                    "stop_loss": sig.stop_loss,
                    "take_profit": sig.take_profit,
                    "confidence": sig.confidence,
                    "timestamp": sig.timestamp,
                    "strategy_name": sig.strategy_name,
                }
                for sig in signals
            ],
            "count": len(signals),
        }

    def _manage_positions(self, parameters: Dict[str, Any]) -> Any:
        """
        Manage positions

        Args:
            parameters: Parameters including positions and strategy config

        Returns:
            List of order actions
        """
        positions = parameters.get("positions", [])
        strategy_config = parameters.get("parameters", {})

        if not strategy_config:
            raise ValueError("parameters (strategy config) is required for position management")

        logger.info(f"Managing {len(positions)} positions")

        # Convert position dicts to Position objects if needed
        from openfund_agent.models.trading import Position

        position_objects = []
        for pos in positions:
            if isinstance(pos, dict):
                position_objects.append(Position(**pos))
            else:
                position_objects.append(pos)

        order_actions = self.executor.manage_positions(
            positions=position_objects, strategy_config=strategy_config
        )

        return {
            "success": True,
            "orders": [
                {
                    "action_type": order.action_type,
                    "symbol": order.symbol,
                    "side": order.side,
                    "quantity": order.quantity,
                    "price": order.price,
                    "stop_loss": order.stop_loss,
                    "take_profit": order.take_profit,
                    "reason": order.reason,
                }
                for order in order_actions
            ],
            "count": len(order_actions),
        }

    def _execute_strategy(self, parameters: Dict[str, Any]) -> Any:
        """
        Execute complete strategy

        Args:
            parameters: Parameters including strategy_name, symbol, and parameters

        Returns:
            Execution result
        """
        strategy_name = parameters["strategy_name"]
        symbol = parameters.get("symbol")
        strategy_params = parameters.get("parameters", {})

        if not symbol:
            raise ValueError("symbol is required for strategy execution")

        logger.info(f"Executing strategy {strategy_name} for {symbol}")

        result = self.executor.execute_strategy(
            strategy_name=strategy_name, symbol=symbol, parameters=strategy_params
        )

        return {
            "success": result.success,
            "signals": [
                {
                    "symbol": sig.symbol,
                    "side": sig.side,
                    "entry_price": sig.entry_price,
                    "stop_loss": sig.stop_loss,
                    "take_profit": sig.take_profit,
                    "confidence": sig.confidence,
                    "timestamp": sig.timestamp,
                }
                for sig in result.signals
            ],
            "orders": [
                {
                    "action_type": order.action_type,
                    "symbol": order.symbol,
                    "side": order.side,
                    "quantity": order.quantity,
                    "price": order.price,
                    "stop_loss": order.stop_loss,
                    "take_profit": order.take_profit,
                    "reason": order.reason,
                }
                for order in result.orders
            ],
            "errors": result.errors,
            "execution_time": result.execution_time,
            "metadata": result.metadata,
        }
