"""
Утилиты для работы с типами контента и чатов
"""
from typing import Final, Optional, Dict, Any
from enum import Enum

from aiogram.types import Message
from aiogram.enums import ContentType, ChatType

__all__ = (
    'CHAT_TYPES_RU',
    'CONTENT_TYPES_RU',
    'CONTENT_EMOJI',
    'get_chat_type',
    'get_content_type',
    'get_content_text',
    'get_content_emoji',
    'get_media_info',
    'has_media',
    'has_text',
    'format_content_info',
    'ContentCategory',
    'get_content_category',
    'is_private_chat',
    'is_group_chat',
    'is_channel',
    'type_msg',
    'type_chat'
)

# ==================== КОНСТАНТЫ ====================

# Типы чатов на русском
CHAT_TYPES_RU: Final[Dict[str, str]] = {
    ChatType.PRIVATE: "Личные сообщения",
    ChatType.GROUP: "Группа",
    ChatType.SUPERGROUP: "Супергруппа",
    ChatType.CHANNEL: "Канал",
    "private": "Личные сообщения",
    "group": "Группа",
    "supergroup": "Супергруппа",
    "channel": "Канал",
}

# Типы контента на русском
CONTENT_TYPES_RU: Final[Dict[str, str]] = {
    # Текст и медиа
    ContentType.TEXT: "Текст",
    ContentType.ANIMATION: "GIF анимация",
    ContentType.AUDIO: "Аудиофайл",
    ContentType.DOCUMENT: "Документ",
    ContentType.PHOTO: "Фотография",
    ContentType.STICKER: "Стикер",
    ContentType.VIDEO: "Видео",
    ContentType.VIDEO_NOTE: "Видеосообщение",
    ContentType.VOICE: "Голосовое сообщение",

    # Контакты и локации
    ContentType.CONTACT: "Контакт",
    ContentType.LOCATION: "Геолокация",
    ContentType.VENUE: "Место на карте",

    # Игры и развлечения
    ContentType.DICE: "Игральная кость",
    ContentType.GAME: "Игра",
    ContentType.POLL: "Опрос",

    # События чата
    ContentType.NEW_CHAT_MEMBERS: "Новые участники",
    ContentType.LEFT_CHAT_MEMBER: "Участник покинул чат",
    ContentType.NEW_CHAT_TITLE: "Изменено название чата",
    ContentType.NEW_CHAT_PHOTO: "Изменена аватарка чата",
    ContentType.DELETE_CHAT_PHOTO: "Удалена аватарка чата",
    ContentType.GROUP_CHAT_CREATED: "Группа создана",
    ContentType.SUPERGROUP_CHAT_CREATED: "Супергруппа создана",
    ContentType.CHANNEL_CHAT_CREATED: "Канал создан",
    ContentType.MESSAGE_AUTO_DELETE_TIMER_CHANGED: "Изменён таймер автоудаления",
    ContentType.MIGRATE_TO_CHAT_ID: "Миграция в супергруппу",
    ContentType.MIGRATE_FROM_CHAT_ID: "Миграция из группы",
    ContentType.PINNED_MESSAGE: "Закреплено сообщение",

    # Платежи
    ContentType.INVOICE: "Счёт на оплату",
    ContentType.SUCCESSFUL_PAYMENT: "Успешная оплата",

    # Другое
    ContentType.CONNECTED_WEBSITE: "Подключён сайт",
    ContentType.PASSPORT_DATA: "Данные Telegram Passport",
    ContentType.PROXIMITY_ALERT_TRIGGERED: "Сработал алерт приближения",

    # Видеочаты
    ContentType.VIDEO_CHAT_SCHEDULED: "Запланирован видеочат",
    ContentType.VIDEO_CHAT_STARTED: "Начался видеочат",
    ContentType.VIDEO_CHAT_ENDED: "Завершён видеочат",
    ContentType.VIDEO_CHAT_PARTICIPANTS_INVITED: "Приглашены в видеочат",

    # Web App
    ContentType.WEB_APP_DATA: "Данные Web App",

    # Форумы
    ContentType.FORUM_TOPIC_CREATED: "Создана тема форума",
    ContentType.FORUM_TOPIC_EDITED: "Изменена тема форума",
    ContentType.FORUM_TOPIC_CLOSED: "Закрыта тема форума",
    ContentType.FORUM_TOPIC_REOPENED: "Открыта тема форума",
    ContentType.GENERAL_FORUM_TOPIC_HIDDEN: "Скрыта общая тема",
    ContentType.GENERAL_FORUM_TOPIC_UNHIDDEN: "Показана общая тема",

    # Розыгрыши
    ContentType.GIVEAWAY_CREATED: "Создан розыгрыш",
    ContentType.GIVEAWAY: "Розыгрыш",
    ContentType.GIVEAWAY_WINNERS: "Победители розыгрыша",
    ContentType.GIVEAWAY_COMPLETED: "Завершён розыгрыш",

    # Истории и реакции
    ContentType.STORY: "История",
}

# Эмодзи для типов контента
CONTENT_EMOJI: Final[Dict[str, str]] = {
    ContentType.TEXT: "💬",
    ContentType.ANIMATION: "🎞️",
    ContentType.AUDIO: "🎵",
    ContentType.DOCUMENT: "📄",
    ContentType.PHOTO: "📷",
    ContentType.STICKER: "🎨",
    ContentType.VIDEO: "🎥",
    ContentType.VIDEO_NOTE: "🎬",
    ContentType.VOICE: "🎤",
    ContentType.CONTACT: "👤",
    ContentType.LOCATION: "📍",
    ContentType.VENUE: "🏢",
    ContentType.DICE: "🎲",
    ContentType.GAME: "🎮",
    ContentType.POLL: "📊",
    ContentType.INVOICE: "💰",
    ContentType.SUCCESSFUL_PAYMENT: "✅",
}


class ContentCategory(str, Enum):
    """Категории контента"""
    TEXT = "text"  # Текстовые сообщения
    MEDIA = "media"  # Медиа (фото, видео, и т.д.)
    FILE = "file"  # Файлы и документы
    VOICE = "voice"  # Голосовые сообщения
    LOCATION = "location"  # Локации и места
    INTERACTION = "interaction"  # Игры, опросы, кости
    SERVICE = "service"  # Служебные сообщения
    PAYMENT = "payment"  # Платежи
    UNKNOWN = "unknown"  # Неизвестный тип


# ==================== ОСНОВНЫЕ ФУНКЦИИ ====================

def get_chat_type(message: Message, russian: bool = True) -> str:
    """
    Возвращает тип чата.

    Args:
        message: Объект сообщения
        russian: Вернуть на русском языке

    Returns:
        str: Тип чата

    Example:
        >>> get_chat_type(message)
        'Личные сообщения'
        >>> get_chat_type(message, russian=False)
        'private'
    """
    chat_type = message.chat.type

    if russian:
        return CHAT_TYPES_RU.get(chat_type, f"Неизвестный тип ({chat_type})")

    return chat_type


def get_content_type(message: Message, russian: bool = True) -> str:
    """
    Возвращает тип контента сообщения.

    Args:
        message: Объект сообщения
        russian: Вернуть на русском языке

    Returns:
        str: Тип контента

    Example:
        >>> get_content_type(message)
        'Фотография'
        >>> get_content_type(message, russian=False)
        'photo'
    """
    content_type = message.content_type

    if russian:
        return CONTENT_TYPES_RU.get(content_type, f"Неизвестный тип ({content_type})")

    return content_type


def get_content_emoji(message: Message) -> str:
    """
    Возвращает эмодзи для типа контента.

    Args:
        message: Объект сообщения

    Returns:
        str: Эмодзи

    Example:
        >>> get_content_emoji(message)
        '📷'
    """
    return CONTENT_EMOJI.get(message.content_type, "📎")


def get_content_text(message: Message, max_length: Optional[int] = None) -> Optional[str]:
    """
    Извлекает текст из сообщения (текст или caption).

    Args:
        message: Объект сообщения
        max_length: Максимальная длина текста (обрезает если больше)

    Returns:
        Optional[str]: Текст сообщения или None

    Example:
        >>> get_content_text(message)
        'Привет, мир!'

        >>> get_content_text(message)  # Фото с подписью
        'Красивое фото'

        >>> get_content_text(message, max_length=10)
        'Привет,...'
    """
    text = message.text or message.caption

    if text and max_length and len(text) > max_length:
        return f"{text[:max_length]}..."

    return text


def has_media(message: Message) -> bool:
    """
    Проверяет, содержит ли сообщение медиа.

    Args:
        message: Объект сообщения

    Returns:
        bool: True если есть медиа

    Example:
        >>> has_media(message)
        True
    """
    media_types = {
        ContentType.PHOTO,
        ContentType.VIDEO,
        ContentType.ANIMATION,
        ContentType.AUDIO,
        ContentType.VOICE,
        ContentType.VIDEO_NOTE,
        ContentType.DOCUMENT,
        ContentType.STICKER
    }

    return message.content_type in media_types


def has_text(message: Message) -> bool:
    """
    Проверяет, есть ли в сообщении текст (или caption).

    Args:
        message: Объект сообщения

    Returns:
        bool: True если есть текст

    Example:
        >>> has_text(message)
        True
    """
    return bool(message.text or message.caption)


# ==================== ДЕТАЛЬНАЯ ИНФОРМАЦИЯ О МЕДИА ====================

def get_media_info(message: Message) -> Dict[str, Any]:
    """
    Возвращает детальную информацию о медиа в сообщении.

    Args:
        message: Объект сообщения

    Returns:
        Dict: Словарь с информацией о медиа

    Example:
        >>> get_media_info(message)
        {
            'type': 'photo',
            'type_ru': 'Фотография',
            'emoji': '📷',
            'has_caption': True,
            'caption': 'Красивое фото',
            'file_size': 123456,
            'file_size_mb': 0.12,
            'width': 1920,
            'height': 1080,
            'duration': None
        }
    """
    info = {
        'type': message.content_type,
        'type_ru': get_content_type(message),
        'emoji': get_content_emoji(message),
        'has_caption': bool(message.caption),
        'caption': message.caption,
        'has_text': bool(message.text),
        'text': message.text,
    }

    # Фото
    if message.photo:
        largest_photo = max(message.photo, key=lambda p: p.file_size or 0)
        info.update({
            'file_id': largest_photo.file_id,
            'file_unique_id': largest_photo.file_unique_id,
            'file_size': largest_photo.file_size,
            'file_size_kb': round(largest_photo.file_size / 1024, 2) if largest_photo.file_size else None,
            'width': largest_photo.width,
            'height': largest_photo.height,
            'count': len(message.photo)  # Количество размеров
        })

    # Видео
    elif message.video:
        info.update({
            'file_id': message.video.file_id,
            'file_unique_id': message.video.file_unique_id,
            'file_size': message.video.file_size,
            'file_size_mb': round(message.video.file_size / (1024 * 1024), 2) if message.video.file_size else None,
            'width': message.video.width,
            'height': message.video.height,
            'duration': message.video.duration,
            'duration_formatted': _format_duration(message.video.duration) if message.video.duration else None,
            'mime_type': message.video.mime_type,
            'file_name': message.video.file_name
        })

    # Документ
    elif message.document:
        info.update({
            'file_id': message.document.file_id,
            'file_unique_id': message.document.file_unique_id,
            'file_size': message.document.file_size,
            'file_size_mb': round(message.document.file_size / (1024 * 1024),
                                  2) if message.document.file_size else None,
            'file_name': message.document.file_name,
            'mime_type': message.document.mime_type
        })

    # Аудио
    elif message.audio:
        info.update({
            'file_id': message.audio.file_id,
            'file_unique_id': message.audio.file_unique_id,
            'file_size': message.audio.file_size,
            'file_size_mb': round(message.audio.file_size / (1024 * 1024), 2) if message.audio.file_size else None,
            'duration': message.audio.duration,
            'duration_formatted': _format_duration(message.audio.duration) if message.audio.duration else None,
            'performer': message.audio.performer,
            'title': message.audio.title,
            'mime_type': message.audio.mime_type,
            'file_name': message.audio.file_name
        })

    # Голосовое сообщение
    elif message.voice:
        info.update({
            'file_id': message.voice.file_id,
            'file_unique_id': message.voice.file_unique_id,
            'file_size': message.voice.file_size,
            'file_size_kb': round(message.voice.file_size / 1024, 2) if message.voice.file_size else None,
            'duration': message.voice.duration,
            'duration_formatted': _format_duration(message.voice.duration) if message.voice.duration else None,
            'mime_type': message.voice.mime_type
        })

    # Видеосообщение
    elif message.video_note:
        info.update({
            'file_id': message.video_note.file_id,
            'file_unique_id': message.video_note.file_unique_id,
            'file_size': message.video_note.file_size,
            'file_size_kb': round(message.video_note.file_size / 1024, 2) if message.video_note.file_size else None,
            'duration': message.video_note.duration,
            'duration_formatted': _format_duration(
                message.video_note.duration) if message.video_note.duration else None,
            'length': message.video_note.length  # Диаметр
        })

    # Анимация (GIF)
    elif message.animation:
        info.update({
            'file_id': message.animation.file_id,
            'file_unique_id': message.animation.file_unique_id,
            'file_size': message.animation.file_size,
            'file_size_mb': round(message.animation.file_size / (1024 * 1024),
                                  2) if message.animation.file_size else None,
            'width': message.animation.width,
            'height': message.animation.height,
            'duration': message.animation.duration,
            'duration_formatted': _format_duration(message.animation.duration) if message.animation.duration else None,
            'mime_type': message.animation.mime_type,
            'file_name': message.animation.file_name
        })

    # Стикер
    elif message.sticker:
        info.update({
            'file_id': message.sticker.file_id,
            'file_unique_id': message.sticker.file_unique_id,
            'file_size': message.sticker.file_size,
            'width': message.sticker.width,
            'height': message.sticker.height,
            'is_animated': message.sticker.is_animated,
            'is_video': message.sticker.is_video,
            'emoji': message.sticker.emoji,
            'set_name': message.sticker.set_name
        })

    return info


def format_content_info(message: Message, include_text: bool = True, max_text_length: int = 50) -> str:
    """
    Форматирует информацию о контенте в читаемую строку.

    Args:
        message: Объект сообщения
        include_text: Включать текст/caption в описание
        max_text_length: Максимальная длина текста

    Returns:
        str: Отформатированная строка

    Example:
        >>> format_content_info(message)
        '📷 Фотография (1920x1080, 123 KB) + "Красивое фото"'

        >>> format_content_info(message)
        '🎥 Видео (1920x1080, 5.2 MB, 1:30) + "Смотрите это видео"'
    """
    emoji = get_content_emoji(message)
    content_type = get_content_type(message)

    parts = [f"{emoji} {content_type}"]

    # Добавляем детали медиа
    if message.photo:
        largest = max(message.photo, key=lambda p: p.file_size or 0)
        size_kb = largest.file_size / 1024 if largest.file_size else 0
        parts.append(f"({largest.width}x{largest.height}, {size_kb:.1f} KB)")

    elif message.video:
        size_mb = message.video.file_size / (1024 * 1024) if message.video.file_size else 0
        duration = _format_duration(message.video.duration) if message.video.duration else "?"
        parts.append(f"({message.video.width}x{message.video.height}, {size_mb:.1f} MB, {duration})")

    elif message.document:
        size_mb = message.document.file_size / (1024 * 1024) if message.document.file_size else 0
        file_name = message.document.file_name or "без имени"
        parts.append(f'("{file_name}", {size_mb:.2f} MB)')

    elif message.audio:
        duration = _format_duration(message.audio.duration) if message.audio.duration else "?"
        title = message.audio.title or "без названия"
        parts.append(f'("{title}", {duration})')

    elif message.voice:
        duration = _format_duration(message.voice.duration) if message.voice.duration else "?"
        parts.append(f"({duration})")

    elif message.video_note:
        duration = _format_duration(message.video_note.duration) if message.video_note.duration else "?"
        parts.append(f"({duration})")

    elif message.sticker:
        emoji_text = message.sticker.emoji or ""
        parts.append(f"({emoji_text})")

    # Добавляем текст/caption
    if include_text:
        text = get_content_text(message, max_length=max_text_length)
        if text:
            parts.append(f'+ "{text}"')

    return ' '.join(parts)


def get_content_category(message: Message) -> ContentCategory:
    """
    Определяет категорию контента.

    Args:
        message: Объект сообщения

    Returns:
        ContentCategory: Категория контента

    Example:
        >>> get_content_category(message)
        ContentCategory.MEDIA
    """
    content_type = message.content_type

    # Текст
    if content_type == ContentType.TEXT:
        return ContentCategory.TEXT

    # Медиа
    if content_type in {ContentType.PHOTO, ContentType.VIDEO, ContentType.ANIMATION, ContentType.STICKER}:
        return ContentCategory.MEDIA

    # Файлы
    if content_type in {ContentType.DOCUMENT, ContentType.AUDIO}:
        return ContentCategory.FILE

    # Голосовые
    if content_type in {ContentType.VOICE, ContentType.VIDEO_NOTE}:
        return ContentCategory.VOICE

    # Локации
    if content_type in {ContentType.LOCATION, ContentType.VENUE}:
        return ContentCategory.LOCATION

    # Интерактивные
    if content_type in {ContentType.DICE, ContentType.GAME, ContentType.POLL}:
        return ContentCategory.INTERACTION

    # Платежи
    if content_type in {ContentType.INVOICE, ContentType.SUCCESSFUL_PAYMENT}:
        return ContentCategory.PAYMENT

    # Служебные
    if content_type in {
        ContentType.NEW_CHAT_MEMBERS,
        ContentType.LEFT_CHAT_MEMBER,
        ContentType.NEW_CHAT_TITLE,
        ContentType.PINNED_MESSAGE
    }:
        return ContentCategory.SERVICE

    return ContentCategory.UNKNOWN


# ==================== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ====================

def _format_duration(seconds: int) -> str:
    """
    Форматирует длительность в читаемый вид.

    Args:
        seconds: Длительность в секундах

    Returns:
        str: Отформатированная строка (MM:SS или HH:MM:SS)

    Example:
        >>> _format_duration(90)
        '1:30'
        >>> _format_duration(3661)
        '1:01:01'
    """
    hours = seconds // 3600
    minutes = (seconds % 3600) // 60
    secs = seconds % 60

    if hours > 0:
        return f"{hours}:{minutes:02d}:{secs:02d}"
    else:
        return f"{minutes}:{secs:02d}"


def is_private_chat(message: Message) -> bool:
    """Проверяет, является ли чат личным"""
    return message.chat.type == ChatType.PRIVATE


def is_group_chat(message: Message) -> bool:
    """Проверяет, является ли чат группой"""
    return message.chat.type in {ChatType.GROUP, ChatType.SUPERGROUP}


def is_channel(message: Message) -> bool:
    """Проверяет, является ли чат каналом"""
    return message.chat.type == ChatType.CHANNEL


# Алиасы для обратной совместимости
type_msg = get_content_type
type_chat = get_chat_type
