"""
Фильтры для обработки callback-запросов
"""
import re
from typing import Union

from aiogram.filters import BaseFilter
from aiogram.types import CallbackQuery

from middleware.loggers import logger

__all__ = (
    'CallbackStartsWith',
    'CallbackEndsWith',
    'CallbackContains',
    'CallbackMatches',
    'CallbackIn'
)


class CallbackStartsWith(BaseFilter):
    """
    Проверяет, начинается ли callback_data с указанного префикса.

    Attributes:
        prefix: Префикс для проверки (строка или список строк)
        ignore_case: Игнорировать регистр

    Example:
        ```python
        # Один префикс
        @router.callback_query(CallbackStartsWith("menu:"))
        async def menu_handler(callback: CallbackQuery):
            await callback.answer("Меню")

        # Несколько префиксов
        @router.callback_query(CallbackStartsWith(["admin:", "mod:"]))
        async def admin_handler(callback: CallbackQuery):
            await callback.answer("Админ панель")
        ```
    """

    def __init__(self, prefix: Union[str, list[str]], ignore_case: bool = True):
        """
        Args:
            prefix: Префикс или список префиксов
            ignore_case: Игнорировать регистр букв
        """
        self.prefixes = [prefix] if isinstance(prefix, str) else prefix
        self.ignore_case = ignore_case

        if self.ignore_case:
            self.prefixes = [p.lower() for p in self.prefixes]

    async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]:
        if not callback.data:
            return False

        data = callback.data.lower() if self.ignore_case else callback.data

        for prefix in self.prefixes:
            if data.startswith(prefix):
                # Извлекаем данные после префикса
                value = callback.data[len(prefix):]

                logger.debug(
                    f"Callback с префиксом '{prefix}': {callback.data}",
                    log_type='CALLBACK'
                )

                return {
                    'matched': True,
                    'prefix': prefix,
                    'value': value,
                    'full_data': callback.data
                }

        return False


class CallbackEndsWith(BaseFilter):
    """
    Проверяет, заканчивается ли callback_data на указанный суффикс.

    Example:
        ```python
        @router.callback_query(CallbackEndsWith(":confirm"))
        async def confirm_handler(callback: CallbackQuery, matched: dict):
            action = matched['value']
            await callback.answer(f"Подтверждение: {action}")
        ```
    """

    def __init__(self, suffix: Union[str, list[str]], ignore_case: bool = True):
        """
        Args:
            suffix: Суффикс или список суффиксов
            ignore_case: Игнорировать регистр букв
        """
        self.suffixes = [suffix] if isinstance(suffix, str) else suffix
        self.ignore_case = ignore_case

        if self.ignore_case:
            self.suffixes = [s.lower() for s in self.suffixes]

    async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]:
        if not callback.data:
            return False

        data = callback.data.lower() if self.ignore_case else callback.data

        for suffix in self.suffixes:
            if data.endswith(suffix):
                # Извлекаем данные до суффикса
                value = callback.data[:-len(suffix)]

                return {
                    'matched': True,
                    'suffix': suffix,
                    'value': value,
                    'full_data': callback.data
                }

        return False


class CallbackContains(BaseFilter):
    """
    Проверяет, содержит ли callback_data указанную подстроку.

    Example:
        ```python
        @router.callback_query(CallbackContains("delete"))
        async def delete_handler(callback: CallbackQuery):
            await callback.answer("Удаление...")
        ```
    """

    def __init__(self, substring: Union[str, list[str]], ignore_case: bool = True):
        """
        Args:
            substring: Подстрока или список подстрок
            ignore_case: Игнорировать регистр букв
        """
        self.substrings = [substring] if isinstance(substring, str) else substring
        self.ignore_case = ignore_case

        if self.ignore_case:
            self.substrings = [s.lower() for s in self.substrings]

    async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]:
        if not callback.data:
            return False

        data = callback.data.lower() if self.ignore_case else callback.data

        for substring in self.substrings:
            if substring in data:
                return {
                    'matched': True,
                    'substring': substring,
                    'full_data': callback.data
                }

        return False


class CallbackMatches(BaseFilter):
    """
    Проверяет callback_data по regex паттерну.

    Example:
        ```python
        # Паттерн: user_123, user_456 и т.д.
        @router.callback_query(CallbackMatches(r"^user_(\d+)$"))
        async def user_handler(callback: CallbackQuery, matched: dict):
            user_id = matched['groups']
            await callback.answer(f"Пользователь {user_id}")
        ```
    """

    def __init__(self, pattern: Union[str, re.Pattern], flags: int = 0):
        """
        Args:
            pattern: Regex паттерн (строка или скомпилированный Pattern)
            flags: Флаги для regex (например, re.IGNORECASE)
        """
        if isinstance(pattern, str):
            self.pattern = re.compile(pattern, flags)
        else:
            self.pattern = pattern

    async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]:
        if not callback.data:
            return False

        match = self.pattern.match(callback.data)

        if match:
            logger.debug(
                f"Callback соответствует паттерну {self.pattern.pattern}: {callback.data}",
                log_type='CALLBACK'
            )

            return {
                'matched': True,
                'pattern': self.pattern.pattern,
                'groups': match.groups(),
                'groupdict': match.groupdict(),
                'full_data': callback.data
            }

        return False


class CallbackIn(BaseFilter):
    """
    Проверяет, находится ли callback_data в списке разрешенных значений.

    Example:
        ```python
        @router.callback_query(CallbackIn(["yes", "no", "cancel"]))
        async def choice_handler(callback: CallbackQuery):
            choice = callback.data
            await callback.answer(f"Выбрано: {choice}")
        ```
    """

    def __init__(self, values: list[str], ignore_case: bool = True):
        """
        Args:
            values: Список разрешенных значений
            ignore_case: Игнорировать регистр букв
        """
        self.values = values
        self.ignore_case = ignore_case

        if self.ignore_case:
            self.values = [v.lower() for v in values]

    async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]:
        if not callback.data:
            return False

        data = callback.data.lower() if self.ignore_case else callback.data

        if data in self.values:
            return {
                'matched': True,
                'value': callback.data
            }

        return False
