"""Simulated order executor."""

from __future__ import annotations

import uuid
from typing import Any, Callable, List, Optional

from sd_api.logging import get_logger
from sd_api.models.signal import TradeSignal
from sd_api.trading.orders import OrderRequest
from sd_api.trading.feedback import OrderFeedback

logger = get_logger("trading.executor")


class SimulatedExecutor:
    """In-memory simulated order executor.

    Modes
    -----
    print_mode : echo each order to stdout/log (default).
    callback_mode : invoke a user-provided function with each OrderFeedback.
    queue_mode : store all feedback in memory (feedback_history).

    Usage::

        executor = SimulatedExecutor()
        executor.mode = "print"  # default
        feedback = executor.send_order(OrderRequest(...))
        print(feedback.ok, feedback.order_id)
    """

    def __init__(
        self,
        mode: str = "print",
        callback: Optional[Callable[[OrderFeedback], None]] = None,
    ) -> None:
        """
        Parameters
        ----------
        mode : str
            One of "print", "callback", "queue".
        callback : Callable, optional
            Only used when mode="callback".
        """
        valid_modes = ("print", "callback", "queue")
        if mode not in valid_modes:
            raise ValueError(f"mode must be one of {valid_modes}")
        self.mode = mode
        self.callback = callback
        self._feedback_history: List[OrderFeedback] = []

    def send_order(self, order: OrderRequest) -> OrderFeedback:
        """Execute a simulated order and return feedback.

        Parameters
        ----------
        order : OrderRequest

        Returns
        -------
        OrderFeedback
        """
        feedback = self._simulate(order)
        self._dispatch(feedback)
        return feedback

    def send_signal(self, signal: TradeSignal) -> OrderFeedback:
        """Convert a TradeSignal to an OrderRequest and execute it.

        Uses a default volume of 0.01 lots if not specified in extra.
        """
        volume = signal.extra.get("volume", 0.01)
        order = OrderRequest(
            symbol=signal.symbol,
            side=signal.side.upper(),
            price=signal.price,
            volume=volume,
            comment=signal.reason,
            extra={"confidence": signal.confidence, "signal_ts_ms": signal.ts_ms},
        )
        return self.send_order(order)

    def _simulate(self, order: OrderRequest) -> OrderFeedback:
        """Generate simulated fill feedback."""
        fill_price = order.price if order.price > 0 else 2000.0
        order_id = f"SIM-{uuid.uuid4().hex[:8].upper()}"
        logger.info(
            f"[SIM] {order.side} {order.volume} lots {order.symbol} "
            f"@ {fill_price:.5f} [SL={order.stop_loss} TP={order.take_profit}]"
        )
        return OrderFeedback.success(
            order_id=order_id,
            fill_price=fill_price,
            message=f"{order.side} order simulated",
        )

    def _dispatch(self, feedback: OrderFeedback) -> None:
        if self.mode == "print":
            print(f"[Executor] {feedback.message} | id={feedback.order_id} | ok={feedback.ok}")
        elif self.mode == "callback" and self.callback:
            self.callback(feedback)
        if self.mode == "queue":
            self._feedback_history.append(feedback)

    @property
    def feedback_history(self) -> List[OrderFeedback]:
        """Return all feedback entries (only in queue mode)."""
        return list(self._feedback_history)

    def clear_history(self) -> None:
        """Clear the feedback history."""
        self._feedback_history.clear()
