import asyncio
import logging
from pathlib import Path

from aiogram import Bot, Dispatcher
from aiogram.client.default import DefaultBotProperties
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.enums import ParseMode
from aiogram.exceptions import TelegramNetworkError
from aiogram.types import BotCommand

from app.bot.handlers.main import build_router
from app.config import Settings
from app.db.session import create_engine_and_session_factory, ensure_database_exists, init_db
from app.services.bot_config_service import BotConfigService
from app.services.notification_service import SubscriptionNotificationService
from app.services.payment_service import PaymentService
from app.services.remnawave_client import RemnawaveApiClient
from app.services.support_ticket_service import SupportTicketService
from app.services.sync_service import SyncService


async def main() -> None:
    settings = Settings()

    logging.basicConfig(
        level=getattr(logging, settings.log_level.upper(), logging.INFO),
        format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
    )

    logger = logging.getLogger(__name__)
    engine = None
    remnawave_client = None
    bot = None

    try:
        if settings.create_database_on_start:
            logger.info(
                "Ensuring MariaDB database '%s' exists on %s:%s",
                settings.db_name,
                settings.db_host,
                settings.db_port,
            )
            await ensure_database_exists(
                settings.database_server_url,
                settings.db_name,
                echo=settings.db_echo,
            )

        engine, session_factory = create_engine_and_session_factory(
            settings.database_url,
            echo=settings.db_echo,
        )

        if settings.create_tables_on_start:
            await init_db(engine)

        remnawave_client = RemnawaveApiClient(
            base_url=settings.remnawave_base_url,
            api_token=settings.remnawave_api_token,
            caddy_api_key=settings.remnawave_caddy_api_key,
            timeout_seconds=settings.remnawave_timeout_seconds,
        )
        sync_service = SyncService(
            settings=settings,
            session_factory=session_factory,
            remnawave_client=remnawave_client,
        )
        bot_config_service = BotConfigService(
            settings=settings,
            session_factory=session_factory,
        )
        support_ticket_service = SupportTicketService(session_factory=session_factory)
        payment_service = PaymentService(
            settings=settings,
            session_factory=session_factory,
            remnawave_client=remnawave_client,
            sync_service=sync_service,
            config_service=bot_config_service,
        )

        bot_session = AiohttpSession(proxy=settings.telegram_proxy_url or None)
        bot = Bot(
            token=settings.bot_token,
            session=bot_session,
            default=DefaultBotProperties(parse_mode=ParseMode.HTML),
        )
        dispatcher = Dispatcher()
        dispatcher.include_router(
            build_router(
                settings=settings,
                sync_service=sync_service,
                support_ticket_service=support_ticket_service,
                payment_service=payment_service,
                bot_config_service=bot_config_service,
            )
        )

        await bot.set_my_commands(
            [
                BotCommand(command="start", description="Открыть главное меню"),
            ]
        )

        project_root = Path(__file__).resolve().parent.parent
        notification_service = SubscriptionNotificationService(
            session_factory=session_factory,
            sync_service=sync_service,
            config_service=bot_config_service,
            project_root=project_root,
        )
        notification_task = asyncio.create_task(
            notification_service.run_periodic(bot),
        )

        try:
            await dispatcher.start_polling(bot)
        finally:
            notification_task.cancel()
            try:
                await notification_task
            except asyncio.CancelledError:
                pass
    except TelegramNetworkError:
        logger.exception(
            "Cannot reach Telegram API. Check outbound HTTPS access to api.telegram.org:443, DNS, firewall, VPN, or proxy."
        )
        raise
    finally:
        if remnawave_client is not None:
            await remnawave_client.close()
        if bot is not None:
            await bot.session.close()
        if engine is not None:
            await engine.dispose()
