from __future__ import annotations

import asyncio
import logging
import time
from contextlib import asynccontextmanager
from typing import AsyncGenerator

import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

import api.routes as _routes
from api.routes import router, set_aggregator
from config.settings import settings
from execution_client.client import execution_client
from risk.manager import risk_manager
from signals.aggregator import SignalAggregator
from signals.decision import decision_engine
from stats.tracker import stats_tracker
from trades.monitor import trade_monitor
from trades.tracker import trade_tracker

logging.basicConfig(
    level=settings.LOG_LEVEL,
    format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
    datefmt="%Y-%m-%dT%H:%M:%S",
)
logger = logging.getLogger(__name__)


async def _on_signal_flush(symbol: str, score: float, signal_count: int) -> None:
    """
    يُستدعى من SignalAggregator عند انتهاء النافذة الزمنية.
    ينفذ: قرار → تحقق → إرسال أمر → تسجيل صفقة.
    """
    decision = decision_engine.decide(symbol, score, signal_count)

    if decision.action == "HOLD":
        logger.info(f"HOLD لـ {symbol} | score={score:.3f}")
        return

    # لا تفتح صفقة إذا كان هناك صفقة مفتوحة بالفعل
    if trade_tracker.has_open_trade(symbol):
        logger.info(f"تجاهل {decision.action} {symbol} — صفقة مفتوحة بالفعل")
        return

    # جلب السعر من execution-bot
    price = await execution_client.get_price(symbol)
    if price is None:
        logger.error(f"لا يوجد سعر لـ {symbol} — تم تخطي الصفقة")
        return

    # حساب حجم الصفقة و TP/SL
    quantity = risk_manager.calculate_quantity(price, stats_tracker.balance)
    take_profit, stop_loss = risk_manager.calculate_tp_sl(decision.action, price)

    # إرسال الأمر إلى execution-bot
    success = await execution_client.send_signal(symbol, decision.action, quantity)
    if not success:
        logger.error(f"فشل إرسال أمر {decision.action} {symbol} لـ execution-bot")
        return

    # تسجيل الصفقة
    trade_tracker.open_trade(
        symbol=symbol,
        action=decision.action,
        quantity=quantity,
        entry_price=price,
        take_profit=take_profit,
        stop_loss=stop_loss,
    )


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    # ── بدء التشغيل ──────────────────────────────────────────────────────────
    logger.info(f"Brain Bot يبدأ | المنفذ={settings.PORT}")

    # 1. تهيئة HTTP client
    await execution_client.start()

    # 2. إنشاء مجمِّع الإشارات مع ربطه بدالة القرار
    aggregator = SignalAggregator(on_flush=_on_signal_flush)
    set_aggregator(aggregator)

    # 3. بدء مراقب الصفقات
    await trade_monitor.start(execution_client.get_price)

    # 4. ضبط وقت البدء
    _routes._startup_time = time.time()

    logger.info(
        f"Brain Bot جاهز | "
        f"threshold=±{settings.DECISION_THRESHOLD} | "
        f"نافذة={settings.SIGNAL_WINDOW}s | "
        f"رصيد={settings.INITIAL_BALANCE} USDT"
    )
    yield

    # ── الإيقاف ──────────────────────────────────────────────────────────────
    logger.info("Brain Bot يتوقف...")
    await trade_monitor.stop()
    await execution_client.stop()
    logger.info("Brain Bot توقف بنجاح")


app = FastAPI(
    title="Brain Orchestrator Bot",
    description="العقل المركزي لنظام التداول — يجمع الإشارات ويرسل الأوامر",
    version="1.0.0",
    lifespan=lifespan,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(router)


if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=False,
        log_level=settings.LOG_LEVEL.lower(),
    )
