import logging
from typing import Callable, Dict, Any, Awaitable
from aiogram import BaseMiddleware
from aiogram.types import TelegramObject, CallbackQuery, Message
from aiogram.exceptions import TelegramBadRequest

logger = logging.getLogger(__name__)


class GlobalErrorMiddleware(BaseMiddleware):
    
    async def __call__(
        self,
        handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
        event: TelegramObject,
        data: Dict[str, Any]
    ) -> Any:
        try:
            return await handler(event, data)
        except TelegramBadRequest as e:
            return await self._handle_telegram_error(event, e)
        except Exception as e:
            logger.error(f"Неожиданная ошибка в GlobalErrorMiddleware: {e}", exc_info=True)
            raise
    
    async def _handle_telegram_error(self, event: TelegramObject, error: TelegramBadRequest):
        error_message = str(error).lower()
        
        if self._is_old_query_error(error_message):
            return await self._handle_old_query(event, error)
        elif self._is_message_not_modified_error(error_message):
            return await self._handle_message_not_modified(event, error)
        elif self._is_bad_request_error(error_message):
            return await self._handle_bad_request(event, error)
        else:
            logger.error(f"Неизвестная Telegram API ошибка: {error}")
            raise error
    
    def _is_old_query_error(self, error_message: str) -> bool:
        return any(phrase in error_message for phrase in [
            "query is too old",
            "query id is invalid",
            "response timeout expired"
        ])
    
    def _is_message_not_modified_error(self, error_message: str) -> bool:
        return "message is not modified" in error_message
    
    def _is_bad_request_error(self, error_message: str) -> bool:
        return any(phrase in error_message for phrase in [
            "message not found",
            "chat not found",
            "bot was blocked by the user",
            "user is deactivated"
        ])
    
    async def _handle_old_query(self, event: TelegramObject, error: TelegramBadRequest):
        if isinstance(event, CallbackQuery):
            user_info = self._get_user_info(event)
            logger.warning(f"🕐 [GlobalErrorMiddleware] Игнорируем устаревший callback '{event.data}' от {user_info}")
        else:
            logger.warning(f"🕐 [GlobalErrorMiddleware] Игнорируем устаревший запрос: {error}")
        
        return None
    
    async def _handle_message_not_modified(self, event: TelegramObject, error: TelegramBadRequest):
        logger.debug(f"📝 [GlobalErrorMiddleware] Сообщение не было изменено: {error}")
        
        if isinstance(event, CallbackQuery):
            try:
                await event.answer()
                logger.debug("✅ Успешно ответили на callback после 'message not modified'")
            except TelegramBadRequest as answer_error:
                if not self._is_old_query_error(str(answer_error).lower()):
                    logger.error(f"❌ Ошибка при ответе на callback: {answer_error}")
        
        return None
    
    async def _handle_bad_request(self, event: TelegramObject, error: TelegramBadRequest):
        error_message = str(error).lower()
        
        if "bot was blocked" in error_message:
            user_info = self._get_user_info(event) if hasattr(event, 'from_user') else "Unknown"
            logger.info(f"🚫 [GlobalErrorMiddleware] Бот заблокирован пользователем {user_info}")
            return None
        elif "user is deactivated" in error_message:
            user_info = self._get_user_info(event) if hasattr(event, 'from_user') else "Unknown"
            logger.info(f"👻 [GlobalErrorMiddleware] Пользователь деактивирован {user_info}")
            return None
        elif "chat not found" in error_message or "message not found" in error_message:
            logger.warning(f"🔍 [GlobalErrorMiddleware] Чат или сообщение не найдено: {error}")
            return None
        else:
            logger.error(f"❌ [GlobalErrorMiddleware] Неизвестная bad request ошибка: {error}")
            raise error
    
    def _get_user_info(self, event: TelegramObject) -> str:
        if hasattr(event, 'from_user') and event.from_user:
            if event.from_user.username:
                return f"@{event.from_user.username}"
            else:
                return f"ID:{event.from_user.id}"
        return "Unknown"


class ErrorStatisticsMiddleware(BaseMiddleware):
    
    def __init__(self):
        self.error_counts = {
            'old_queries': 0,
            'message_not_modified': 0,
            'bot_blocked': 0,
            'user_deactivated': 0,
            'other_errors': 0
        }
    
    async def __call__(
        self,
        handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
        event: TelegramObject,
        data: Dict[str, Any]
    ) -> Any:
        try:
            return await handler(event, data)
        except TelegramBadRequest as e:
            self._count_error(e)
            raise  
    
    def _count_error(self, error: TelegramBadRequest):
        error_message = str(error).lower()
        
        if "query is too old" in error_message:
            self.error_counts['old_queries'] += 1
        elif "message is not modified" in error_message:
            self.error_counts['message_not_modified'] += 1
        elif "bot was blocked" in error_message:
            self.error_counts['bot_blocked'] += 1
        elif "user is deactivated" in error_message:
            self.error_counts['user_deactivated'] += 1
        else:
            self.error_counts['other_errors'] += 1
    
    def get_statistics(self) -> dict:
        return self.error_counts.copy()
    
    def reset_statistics(self):
        for key in self.error_counts:
            self.error_counts[key] = 0
