from __future__ import annotations

import asyncio
import logging

from config.settings import settings
from trades.tracker import OpenTrade, trade_tracker
from stats.tracker import stats_tracker

logger = logging.getLogger(__name__)


class TradeMonitor:
    """
    عامل خلفي asyncio.Task.
    كل MONITOR_INTERVAL ثانية يفحص جميع الصفقات المفتوحة ويتحقق من TP/SL.
    """

    def __init__(self) -> None:
        self._task: asyncio.Task | None = None
        # يُحقَن من main.py بعد تهيئة execution_client
        self._get_price: object = None

    async def start(self, get_price_fn) -> None:
        self._get_price = get_price_fn
        self._task = asyncio.create_task(self._monitor_loop(), name="trade-monitor")
        logger.info(f"مراقب الصفقات بدأ | فترة الفحص={settings.MONITOR_INTERVAL}s")

    async def stop(self) -> None:
        if self._task:
            self._task.cancel()
            try:
                await self._task
            except asyncio.CancelledError:
                pass
        logger.info("مراقب الصفقات توقف")

    async def _monitor_loop(self) -> None:
        while True:
            await asyncio.sleep(settings.MONITOR_INTERVAL)
            trades = trade_tracker.get_open_trades()
            if trades:
                await asyncio.gather(
                    *[self._check_trade(t) for t in trades],
                    return_exceptions=True,
                )

    async def _check_trade(self, trade: OpenTrade) -> None:
        price: float | None = await self._get_price(trade.symbol)
        if price is None:
            logger.warning(f"لا يوجد سعر لمراقبة {trade.symbol}")
            return

        # تحديث PnL الحالي
        if trade.action == "BUY":
            trade.pnl_pct = (price - trade.entry_price) / trade.entry_price * 100
        else:
            trade.pnl_pct = (trade.entry_price - price) / trade.entry_price * 100

        if self._hit_take_profit(trade, price):
            logger.info(f"TP اُصطِيد: {trade.symbol} @ {price} | PnL={trade.pnl_pct:+.2f}%")
            self._close_and_record(trade, price)

        elif self._hit_stop_loss(trade, price):
            logger.info(f"SL اُصطِيد: {trade.symbol} @ {price} | PnL={trade.pnl_pct:+.2f}%")
            self._close_and_record(trade, price)

    def _hit_take_profit(self, trade: OpenTrade, price: float) -> bool:
        if trade.action == "BUY":
            return price >= trade.take_profit
        return price <= trade.take_profit

    def _hit_stop_loss(self, trade: OpenTrade, price: float) -> bool:
        if trade.action == "BUY":
            return price <= trade.stop_loss
        return price >= trade.stop_loss

    def _close_and_record(self, trade: OpenTrade, exit_price: float) -> None:
        closed = trade_tracker.close_trade(trade.id, exit_price)
        if closed:
            stats_tracker.record_trade_closed(
                pnl_pct=closed.pnl_pct,
                quantity=closed.quantity,
                entry_price=closed.entry_price,
            )


trade_monitor = TradeMonitor()
