# bot/management/commands/runbots.py
import asyncio
import logging
import signal
from typing import Sequence, Tuple

from django.core.management.base import BaseCommand
from bot.models import TelegramBot, BotConfig
from bot.bot_factory import get_all_active_bots_with_configs, build_application_for_bot

log = logging.getLogger(__name__)

class Command(BaseCommand):
    help = "Запуск ВСЕХ активных ботов (PTB 22.3) в одном процессе."

    def handle(self, *args, **options):
        logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")

        # ВАЖНО: ORM здесь, в синхронном контексте
        bot_cfg_pairs: Sequence[Tuple[TelegramBot, BotConfig]] = get_all_active_bots_with_configs()
        if not bot_cfg_pairs:
            self.stderr.write(self.style.ERROR("Нет активных ботов (is_active=True)."))
            return

        asyncio.run(self._amain(bot_cfg_pairs))

    async def _amain(self, bot_cfg_pairs: Sequence[Tuple[TelegramBot, BotConfig]]):
        apps = []
        try:
            # Ни одной ORM-операции тут — только PTB
            for tb, cfg in bot_cfg_pairs:
                app, allowed_updates = build_application_for_bot(tb, cfg)
                await app.initialize()
                await app.start()
                await app.updater.start_polling(allowed_updates=allowed_updates)
                apps.append(app)
                log.info("Bot started: %s (@%s)", tb.name, tb.username or "—")

            # Ждём SIGINT/SIGTERM
            stop_event = asyncio.Event()

            def _stop(*_):
                stop_event.set()

            loop = asyncio.get_running_loop()
            for sig in (signal.SIGINT, signal.SIGTERM):
                try:
                    loop.add_signal_handler(sig, _stop)
                except NotImplementedError:
                    pass  # Windows

            await stop_event.wait()

        finally:
            for app in reversed(apps):
                try:
                    await app.updater.stop()
                    await app.stop()
                    await app.shutdown()
                except Exception:
                    log.exception("Shutdown error")
            log.info("All bots stopped gracefully.")