import logging
import os

from telegram import Update
from telegram.ext import Application, ChatMemberHandler, CommandHandler, MessageHandler, filters

from bot.config import config
from bot.handlers.common import error_handler, help_command, start
from bot.handlers.dota import add_player, list_players, remove_player
from bot.handlers.gather import abandon, accept, decline, expire_gather, gather, on_chat_member_update, track_member
from bot.handlers.group import group_mention, group_reply
from bot.handlers.private import private_message
from bot.jobs.poll_matches import poll_dota_matches
from bot.services.storage import PlayerStore
from bot.services.stratz import StratzClient
from bot.utils.logging_setup import setup_logging


def main() -> None:
    setup_logging(config.log_level)
    logger = logging.getLogger(__name__)
    logger.info("Starting bot (username=@%s)", config.bot_username)

    os.makedirs(config.data_dir, exist_ok=True)
    store = PlayerStore(path=os.path.join(config.data_dir, "dota_data.json"))
    store.load()
    if not config.stratz_api_key:
        raise RuntimeError(
            "STRATZ_API_KEY environment variable is not set. "
            "Get a free token at https://stratz.com/api."
        )
    stratz = StratzClient(api_key=config.stratz_api_key)
    logger.info("STRATZ client initialized")

    application = Application.builder().token(config.bot_token).build()
    application.bot_data["store"] = store
    application.bot_data["stratz"] = stratz
    application.bot_data["gather_sessions"] = {}

    # Member tracking: join/leave events (primary, requires bot admin)
    application.add_handler(ChatMemberHandler(on_chat_member_update, ChatMemberHandler.CHAT_MEMBER))
    # Member tracking: fallback for pre-existing members via messages (group -1)
    application.add_handler(
        MessageHandler(filters.ChatType.GROUPS & filters.TEXT & ~filters.COMMAND, track_member),
        group=-1,
    )

    # Commands (all chat types)
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("help", help_command))
    application.add_handler(CommandHandler("addplayer", add_player))
    application.add_handler(CommandHandler("removeplayer", remove_player))
    application.add_handler(CommandHandler("listplayers", list_players))
    application.add_handler(CommandHandler("gather", gather))
    application.add_handler(CommandHandler("accept", accept))
    application.add_handler(CommandHandler("decline", decline))
    application.add_handler(CommandHandler("abandon", abandon))

    # Private chat: all non-command text
    application.add_handler(
        MessageHandler(
            filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND,
            private_message,
        )
    )

    # Group: @mention
    application.add_handler(
        MessageHandler(
            filters.ChatType.GROUPS & filters.Mention(config.bot_username),
            group_mention,
        )
    )

    # Group: reply to bot's message
    application.add_handler(
        MessageHandler(
            filters.ChatType.GROUPS & filters.REPLY & filters.TEXT,
            group_reply,
        )
    )

    application.add_error_handler(error_handler)

    # Dota polling job
    application.job_queue.run_repeating(
        poll_dota_matches,
        interval=config.poll_interval,
        first=10,
        name="dota_poll",
    )

    async def on_shutdown(app: Application) -> None:
        await app.bot_data["stratz"].close()

    application.post_shutdown = on_shutdown

    logger.info(
        "Bot is polling. Dota poll interval: %ds. Press Ctrl+C to stop.",
        config.poll_interval,
    )
    application.run_polling(
        allowed_updates=Update.ALL_TYPES,
        drop_pending_updates=config.drop_pending_updates,
    )
    logger.info("Bot has shut down cleanly.")


if __name__ == "__main__":
    main()
