from __future__ import annotations

import asyncio
import os

import structlog
from dotenv import load_dotenv

load_dotenv()
from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import BotCommand

from adapter.telegram import db
from adapter.telegram.handlers import commands, message, settings, start, topic_events
from core.auth import AuthManager
from core.chat import ChatManager
from core.handler import EventDispatcher
from core.settings import SettingsManager
from core.store import InMemoryStore
from sdk.mock import MockPlatformClient

logger = structlog.get_logger(__name__)


class PlatformMiddleware:
    def __init__(self, dispatcher: EventDispatcher) -> None:
        self._dispatcher = dispatcher

    async def __call__(self, handler, event, data):
        data["dispatcher"] = self._dispatcher
        return await handler(event, data)


def build_event_dispatcher() -> EventDispatcher:
    platform = MockPlatformClient()
    store = InMemoryStore()
    return EventDispatcher(
        platform=platform,
        chat_mgr=ChatManager(platform, store),
        auth_mgr=AuthManager(platform, store),
        settings_mgr=SettingsManager(platform, store),
    )


async def main() -> None:
    token = os.environ.get("BOT_TOKEN") or os.environ.get("TELEGRAM_BOT_TOKEN")
    if not token:
        raise RuntimeError("BOT_TOKEN (or TELEGRAM_BOT_TOKEN) env variable is not set")

    db.init_db()

    bot = Bot(token=token)
    dp = Dispatcher(storage=MemoryStorage())
    event_dispatcher = build_event_dispatcher()

    dp.message.middleware(PlatformMiddleware(event_dispatcher))
    dp.callback_query.middleware(PlatformMiddleware(event_dispatcher))

    dp.include_router(topic_events.router)
    dp.include_router(start.router)
    dp.include_router(commands.router)
    dp.include_router(settings.router)
    dp.include_router(message.router)

    await bot.set_my_commands([
        BotCommand(command="start",    description="Начать / восстановить сессию"),
        BotCommand(command="new",      description="Создать новый чат"),
        BotCommand(command="archive",  description="Архивировать текущий чат"),
        BotCommand(command="rename",   description="Переименовать текущий чат"),
        BotCommand(command="settings", description="Настройки"),
    ])

    logger.info("bot_starting")
    await dp.start_polling(bot, allowed_updates=["message", "callback_query"])


if __name__ == "__main__":
    asyncio.run(main())
