import logging
import time
import asyncio
from telegram import Update
from telegram.ext import ContextTypes
from telegram.error import BadRequest, RetryAfter, NetworkError
from states import States
from menus import (
    get_main_menu,
    get_country_menu,
    get_district_menu,
    get_back_to_main_button,
)

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)

CALLBACK_COOLDOWN = 1.0  

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    context.user_data.clear()
    context.user_data['last_callback_time'] = 0
    await update.message.reply_text(
        "Выберите страну",
        reply_markup=get_main_menu(),
    )
    context.user_data['current_state'] = States.MAIN_MENU
    logger.info("Бот запущен, переход в главное меню")
    return States.MAIN_MENU

async def handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    data = query.data

    
    if 'last_query_id' in context.user_data and context.user_data['last_query_id'] == query.id:
        logger.info(f"Дублирующийся callback: {data}, игнорируем")
        return context.user_data.get('current_state', States.MAIN_MENU)

    
    current_time = time.time()
    last_callback_time = context.user_data.get('last_callback_time', 0)
    if current_time - last_callback_time < CALLBACK_COOLDOWN:
        logger.info(f"Слишком частое нажатие: {data}, игнорируем")
        await query.answer(text="Пожалуйста, не нажимайте так быстро!")
        return context.user_data.get('current_state', States.MAIN_MENU)

    context.user_data['last_query_id'] = query.id
    context.user_data['last_callback_time'] = current_time
    logger.info(f"Обработка callback: {data}, текущее состояние: {context.user_data.get('current_state', 'не определено')}")

    async def send_or_edit_message(text, reply_markup):
        try:
            await query.message.edit_text(text, reply_markup=reply_markup)
        except BadRequest as e:
            if "Message can't be edited" in str(e):
                logger.warning(f"Сообщение не может быть отредактировано: {str(e)}, отправляем новое")
                await query.message.reply_text(text, reply_markup=reply_markup)
            else:
                raise e

    try:
        if data == "main_menu":
            context.user_data.clear()
            context.user_data['last_callback_time'] = current_time
            await send_or_edit_message(
                "Выберите страну",
                get_main_menu(),
            )
            context.user_data['current_state'] = States.MAIN_MENU
            logger.info("Переход в главное меню")
            return States.MAIN_MENU

        if data.startswith("country:"):
            country = data.split(":")[1]
            context.user_data["current_country"] = country
            text = "Выберите город" if country in ["Кыргызстан", "Казахстан"] else "Выберите федеральный округ"
            await send_or_edit_message(
                text,
                get_country_menu(country),
            )
            context.user_data['current_state'] = States.COUNTRY if country in ["Кыргызстан", "Казахстан"] else States.FEDERAL_DISTRICT
            logger.info(f"Выбрана страна: {country}, состояние: {context.user_data['current_state']}")
            return context.user_data['current_state']

        if data.startswith("district:"):
            district = data.split(":")[1]
            context.user_data["current_district"] = district
            await send_or_edit_message(
                "Выберите город",
                get_district_menu(district),
            )
            context.user_data['current_state'] = States.CITY
            logger.info(f"Выбран округ: {district}, переход к выбору города")
            return States.CITY

        if data.startswith("city:"):
            city = data.split(":")[1]
            await send_or_edit_message(
                f"Вы выбрали: {city}\nСпасибо! Нажмите «На Главную» или используйте /start, чтобы вернуться в меню.",
                get_back_to_main_button(),
            )
            context.user_data['current_state'] = States.CITY
            logger.info(f"Выбран город: {city}")
            return States.CITY

        logger.warning(f"Неожиданные callback-данные: {data}")
        context.user_data.clear()
        context.user_data['last_callback_time'] = current_time
        await send_or_edit_message(
            "Что-то пошло не так. Возвращаю вас в главное меню.",
            get_main_menu(),
        )
        context.user_data['current_state'] = States.MAIN_MENU
        logger.info("Возврат в главное меню из-за неожиданных данных")
        return States.MAIN_MENU

    except BadRequest as e:
        if "Message is not modified" in str(e):
            logger.info("Сообщение не изменено, игнорируем ошибку")
            return context.user_data.get('current_state', States.MAIN_MENU)
        logger.error(f"Ошибка BadRequest в handle_callback: {str(e)}")
        context.user_data.clear()
        context.user_data['last_callback_time'] = current_time
        await send_or_edit_message(
            "Произошла ошибка. Возвращаю вас в главное меню.",
            get_main_menu(),
        )
        context.user_data['current_state'] = States.MAIN_MENU
        logger.info("Возврат в главное меню из-за BadRequest")
        return States.MAIN_MENU
    except RetryAfter as e:
        logger.warning(f"Превышен лимит Telegram API, ожидание: {e.retry_after} секунд")
        await asyncio.sleep(e.retry_after)
        await send_or_edit_message(
            f"Слишком много запросов. Пожалуйста, попробуйте снова.",
            get_main_menu(),
        )
        context.user_data['current_state'] = States.MAIN_MENU
        logger.info("Возврат в главное меню из-за RetryAfter")
        return States.MAIN_MENU
    except NetworkError as e:
        logger.error(f"Сетевая ошибка: {str(e)}")
        await send_or_edit_message(
            "Сетевая ошибка. Пожалуйста, попробуйте снова.",
            get_main_menu(),
        )
        context.user_data['current_state'] = States.MAIN_MENU
        logger.info("Возврат в главное меню из-за NetworkError")
        return States.MAIN_MENU
    except Exception as e:
        logger.error(f"Общая ошибка в handle_callback: {str(e)}")
        context.user_data.clear()
        context.user_data['last_callback_time'] = current_time
        await send_or_edit_message(
            "Произошла ошибка. Возвращаю вас в главное меню. Попробуйте снова или используйте /start.",
            get_main_menu(),
        )
        context.user_data['current_state'] = States.MAIN_MENU
        logger.info("Возврат в главное меню из-за общей ошибки")
        return States.MAIN_MENU

async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    logger.error(f"Ошибка при обработке {update}: {context.error}")
    context.user_data.clear()
    context.user_data['last_callback_time'] = time.time()
    error_message = (
        "Произошла ошибка. Возвращаю вас в главное меню. Попробуйте снова или используйте /start."
    )
    if update.message:
        await update.message.reply_text(
            error_message,
            reply_markup=get_main_menu(),
        )
    elif update.callback_query:
        try:
            await update.callback_query.message.edit_text(
                error_message,
                reply_markup=get_main_menu(),
            )
        except BadRequest as e:
            if "Message can't be edited" in str(e):
                logger.warning(f"Сообщение не может быть отредактировано в error_handler: {str(e)}, отправляем новое")
                await update.callback_query.message.reply_text(
                    error_message,
                    reply_markup=get_main_menu(),
                )
            else:
                raise e
    context.user_data['current_state'] = States.MAIN_MENU
    logger.info("Возврат в главное меню из error_handler")
    return States.MAIN_MENU