"""
Точка входа PrimoGuard Bot
"""
from asyncio import run
import asyncio
from typing import List

from configs import settings
from bot import bot, dp, BotInfo, WebhookManager, setup_middlewares, router
from database import get_manager
from middleware.loggers import logger

__all__ = ("main",)


def _start_background_tasks_safe() -> List[asyncio.Task]:
    """
    Безопасный запуск фоновых задач с обработкой ошибок.

    Returns:
        List[asyncio.Task]: Список запущенных задач (пустой список если модуль не найден)
    """
    try:
        from bot.tasks import start_background_tasks
        tasks = start_background_tasks()
        logger.info(
            f"🚀 Запущено {len(tasks)} фоновых задач",
            log_type="STARTUP"
        )
        return tasks
    except ImportError:
        logger.warning(
            "⚠️ Модуль 'bot.tasks' не найден, фоновые задачи не запущены",
            log_type="STARTUP"
        )
        return []
    except Exception as e:
        logger.error(
            f"❌ Ошибка запуска фоновых задач: {e}",
            log_type="STARTUP"
        )
        return []


async def setup_services(setup_webhook: bool = True) -> str:
    """
    Инициализация всех сервисов: БД и бот.

    Args:
        setup_webhook: Устанавливать ли webhook в BotInfo.setup()

    Returns:
        str: Username бота
    """
    # База данных
    manager = get_manager()
    await manager.init()

    stats = await manager.get_stats()
    logger.info(
        f"📊 БД инициализирована: {stats.get('total_banwords', 0)} банвордов",
        log_type="DATABASE"
    )

    # Бот: получение информации (БЕЗ webhook)
    await BotInfo.setup(bots=bot, setup_webhook=setup_webhook)

    # ВАЖНО: Регистрируем middleware и роутеры ДО установки webhook
    setup_middlewares(
        dp=dp,
        bot=bot,
        enable_spam_check=settings.ANTI_SPAM,
        channel_ids=[],
    )

    # Подключение маршрутов
    dp.include_router(router)

    logger.info("✓ Все handlers и middleware зарегистрированы", log_type="STARTUP")

    return BotInfo.username


async def on_startup(app) -> None:
    """Выполняется при запуске webhook-сервера."""
    # 1. Инициализируем всё БЕЗ webhook
    username = await setup_services(setup_webhook=False)

    # 2. Запускаем фоновые задачи
    background_tasks = _start_background_tasks_safe()
    app['background_tasks'] = background_tasks

    # 3. ТЕПЕРЬ устанавливаем webhook (когда всё готово)
    webhook = WebhookManager(bot, dp)

    if settings.WEBHOOK_URL:
        success = await webhook.setup(
            webhook_url=settings.WEBHOOK_URL,
            secret_token=settings.SECRET_TOKEN,
            drop_pending_updates=True
        )

        if success:
            logger.success(
                f"✅ Бот @{username} запущен в режиме Webhook",
                log_type="STARTUP"
            )
        else:
            logger.error(
                "❌ Не удалось установить webhook, но сервер запущен",
                log_type="STARTUP"
            )
    else:
        logger.warning(
            "⚠️ WEBHOOK_URL не указан",
            log_type="STARTUP"
        )


async def on_shutdown(app) -> None:
    """Очистка ресурсов при остановке сервера."""
    logger.info("👋 Остановка бота...", log_type="SHUTDOWN")

    try:
        # Отменяем фоновые задачи
        if 'background_tasks' in app and app['background_tasks']:
            tasks = app['background_tasks']
            logger.info(
                f"⏸️ Остановка {len(tasks)} фоновых задач...",
                log_type="SHUTDOWN"
            )

            for task in tasks:
                if not task.done():
                    task.cancel()

            # Ждём завершения с таймаутом 5 секунд
            try:
                await asyncio.wait_for(
                    asyncio.gather(*tasks, return_exceptions=True),
                    timeout=5.0
                )
                logger.info("✅ Фоновые задачи остановлены", log_type="SHUTDOWN")
            except asyncio.TimeoutError:
                logger.warning(
                    "⚠️ Таймаут остановки фоновых задач (5 сек)",
                    log_type="SHUTDOWN"
                )

        # Закрываем соединения
        logger.info("📊 Закрытие базы данных...", log_type="SHUTDOWN")
        await get_manager().close()

        logger.info("🤖 Закрытие сессии бота...", log_type="SHUTDOWN")
        await bot.session.close()

    except Exception as e:
        logger.error(f"❌ Ошибка при закрытии: {e}", log_type="SHUTDOWN")

    logger.success("✅ Бот остановлен", log_type="SHUTDOWN")


def start_webhook() -> None:
    """Запуск в режиме Webhook (синхронный)."""
    logger.setup()

    webhook = WebhookManager(bot, dp)

    # ВАЖНО: Конфигурируем webhook ПЕРЕД on_startup
    webhook.configure()

    # Добавляем startup/shutdown handlers
    webhook.app.on_startup.append(on_startup)
    webhook.app.on_shutdown.append(on_shutdown)

    # Запускаем webhook сервер
    logger.info("🌐 Запуск Webhook сервера...", log_type="MAIN")
    webhook.run()


async def start_polling() -> None:
    """Запуск в режиме Polling (асинхронный)."""
    logger.setup()

    background_tasks: List[asyncio.Task] = []

    try:
        # 1. Инициализируем сервисы
        username = await setup_services(setup_webhook=False)

        # 2. Запускаем фоновые задачи
        background_tasks = _start_background_tasks_safe()

        # 3. Удаляем webhook для polling режима
        webhook = WebhookManager(bot, dp)
        await webhook.delete(drop_pending_updates=True)

        logger.success(
            f"✅ Бот @{username} запущен в режиме Polling",
            log_type="STARTUP"
        )

        # 4. Запускаем polling
        await dp.start_polling(bot, drop_pending_updates=True)

    except KeyboardInterrupt:
        logger.info("⚠️ Получен сигнал остановки (Ctrl+C)", log_type="MAIN")

    except Exception as e:
        logger.critical(
            f"🔥 Критическая ошибка: {e}",
            log_type="MAIN"
        )
        raise

    finally:
        logger.info("🧹 Очистка ресурсов...", log_type="SHUTDOWN")

        try:
            # Отменяем фоновые задачи
            if background_tasks:
                logger.info(
                    f"⏸️ Остановка {len(background_tasks)} фоновых задач...",
                    log_type="SHUTDOWN"
                )

                for task in background_tasks:
                    if not task.done():
                        task.cancel()

                # Ждём завершения с таймаутом 5 секунд
                try:
                    await asyncio.wait_for(
                        asyncio.gather(*background_tasks, return_exceptions=True),
                        timeout=5.0
                    )
                    logger.info("✅ Фоновые задачи остановлены", log_type="SHUTDOWN")
                except asyncio.TimeoutError:
                    logger.warning(
                        "⚠️ Таймаут остановки фоновых задач (5 сек)",
                        log_type="SHUTDOWN"
                    )

            # Закрываем соединения
            logger.info("📊 Закрытие базы данных...", log_type="SHUTDOWN")
            await get_manager().close()

            logger.info("🤖 Закрытие сессии бота...", log_type="SHUTDOWN")
            await bot.session.close()

            logger.success("✅ Бот остановлен", log_type="SHUTDOWN")

        except Exception as e:
            logger.error(
                f"❌ Ошибка при очистке ресурсов: {e}",
                log_type="SHUTDOWN"
            )


def main() -> None:
    """Входная точка проекта."""
    try:
        if settings.WEBHOOK:
            # ========== WEBHOOK РЕЖИМ ==========
            logger.info("🔧 Режим: Webhook", log_type="MAIN")
            start_webhook()
        else:
            # ========== POLLING РЕЖИМ ==========
            logger.info("🔧 Режим: Polling", log_type="MAIN")
            run(start_polling())

    except KeyboardInterrupt:
        logger.info("⚠️ Остановка по сигналу Ctrl+C", log_type="MAIN")

    except Exception as e:
        logger.critical(
            f"🔥 Критическая ошибка при запуске: {e}",
            log_type="MAIN"
        )
        raise


if __name__ == "__main__":
    main()
