import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.database import init_db, AsyncSessionLocal
from app.core.scheduler import start_scheduler, stop_scheduler
from app.engines.trade_monitor import trade_monitor
from app.engines.decision_engine import DecisionEngine
from app.services.trade_service import TradeService
from app.services.telegram_service import telegram_service
from app.strategies.rsi_strategy import RSIStrategy
from app.strategies.ema_crossover import EMACrossoverStrategy
from app.api.routes import bot, trades, strategies, analytics, settings, market
from app.api.routes.market import set_decision_engine
from app.api import websockets
from app.api.websockets import broadcast_trade_event

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
)
logger = logging.getLogger(__name__)

# Default pairs scanned on each bot cycle
WATCHED_PAIRS = [
    "BTC/USDT",
    "ETH/USDT",
    "BNB/USDT",
    "SOL/USDT",
    "XRP/USDT",
]


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Startup and shutdown logic."""
    logger.info("Starting Crypto Trading Bot backend...")

    # Initialise database tables
    await init_db()

    # Build strategies and decision engine
    rsi = RSIStrategy()
    ema = EMACrossoverStrategy()
    decision_engine = DecisionEngine(strategies=[rsi, ema])
    trade_svc = TradeService(decision_engine=decision_engine)

    # Inject decision engine into market route
    set_decision_engine(decision_engine)

    # Wire trade monitor Telegram callbacks
    trade_monitor.on_sl_hit = telegram_service.notify_sl_hit
    trade_monitor.on_tp_hit = telegram_service.notify_tp_hit
    trade_monitor.on_trade_closed = telegram_service.notify_trade_closed

    async def _trade_monitor_job():
        async with AsyncSessionLocal() as db:
            await trade_monitor.check_open_trades(db)

    async def _bot_cycle_job():
        """Scan all watched pairs for signals."""
        async with AsyncSessionLocal() as db:
            for pair in WATCHED_PAIRS:
                try:
                    trade = await trade_svc.run_signal_cycle(pair, db)
                    if trade:
                        await broadcast_trade_event("trade_opened", trade.to_dict())
                except Exception as e:
                    logger.error(f"Bot cycle error for {pair}: {e}")

    start_scheduler(_trade_monitor_job, _bot_cycle_job)

    # Start Telegram command listener
    telegram_service.start_command_listener()

    logger.info("Backend started successfully on port 8002")
    yield

    # Shutdown
    stop_scheduler()
    logger.info("Backend shutdown complete")


app = FastAPI(
    title="Crypto Trading Bot API",
    description="Binance Spot trading bot with RSI and EMA strategies",
    version="1.0.0",
    lifespan=lifespan,
)

# CORS — allow React dev server and same-origin production
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "http://localhost:3001"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Register API routers
app.include_router(bot.router)
app.include_router(trades.router)
app.include_router(strategies.router)
app.include_router(analytics.router)
app.include_router(settings.router)
app.include_router(market.router)
app.include_router(websockets.router)


@app.get("/health")
async def health():
    return {"status": "ok", "service": "crypto-bot-backend"}
