from __future__ import annotations

import asyncio
import logging
import threading
import time
from typing import TYPE_CHECKING

from binance.client import Client
from binance.exceptions import BinanceAPIException

from config.settings import settings
from price.cache import price_cache
from websocket.manager import ws_manager

if TYPE_CHECKING:
    pass

logger = logging.getLogger(__name__)


class PriceUpdater:
    """خيط خلفي يجلب الأسعار من Binance REST ويخزنها في الذاكرة."""

    def __init__(self) -> None:
        self._running = False
        self._thread: threading.Thread | None = None
        self._client: Client | None = None
        self.loop: asyncio.AbstractEventLoop | None = None  # يُضبَط من main.py

    def _get_client(self) -> Client:
        if self._client is None:
            # مفاتيح API غير مطلوبة لقراءة الأسعار العامة
            self._client = Client("", "")
        return self._client

    def start(self) -> None:
        if self._running:
            return
        self._running = True
        self._thread = threading.Thread(target=self._run, daemon=True, name="price-updater")
        self._thread.start()
        logger.info(f"محدِّث الأسعار بدأ | العملات={settings.SYMBOLS} | الفترة={settings.UPDATE_INTERVAL}s")

    def stop(self) -> None:
        self._running = False
        if self._thread:
            self._thread.join(timeout=5)
        logger.info("محدِّث الأسعار توقف")

    def _run(self) -> None:
        client = self._get_client()
        while self._running:
            self._fetch_prices(client)
            time.sleep(settings.UPDATE_INTERVAL)

    def _fetch_prices(self, client: Client) -> None:
        prices: dict[str, float] = {}
        for symbol in settings.SYMBOLS:
            try:
                ticker = client.get_symbol_ticker(symbol=symbol)
                price = float(ticker["price"])
                price_cache.set(symbol, price)
                prices[symbol] = price
            except BinanceAPIException as e:
                logger.warning(f"فشل جلب سعر {symbol}: {e}")
            except Exception as e:
                logger.warning(f"خطأ غير متوقع عند جلب {symbol}: {e}")

        if prices and self.loop:
            self._schedule_broadcast(prices)

    def _schedule_broadcast(self, prices: dict[str, float]) -> None:
        asyncio.run_coroutine_threadsafe(
            ws_manager.broadcast_prices(prices),
            self.loop,
        )


price_updater = PriceUpdater()
