"""
Обработчики команды статистики
"""
from datetime import datetime
from aiogram import Router, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.utils.keyboard import InlineKeyboardBuilder

from bot.filters.admin import IsAdmin
from configs import settings, COMMANDS
from database import get_manager
from middleware.loggers import logger
from bot.utils.decorators import log_action

__all__ = ("router",)

router: Router = Router(name="stats_router")


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

def format_number(num: int) -> str:
    """Форматирует большие числа с разделителями"""
    return f"{num:,}".replace(",", " ")


def create_text_bar(value: int, max_value: int, length: int = 10) -> str:
    """Создает текстовую полоску прогресса"""
    if max_value == 0:
        return "░" * length

    filled = int((value / max_value) * length)
    filled = max(0, min(filled, length))
    empty = length - filled

    return "█" * filled + "░" * empty


def format_datetime(dt: datetime) -> str:
    """Форматирует datetime в читабельный формат"""
    return dt.strftime("%d.%m.%Y %H:%M")


def format_time_remaining(minutes: int) -> str:
    """
    Форматирует оставшееся время в читабельный формат.

    Args:
        minutes: Количество минут

    Returns:
        Отформатированная строка времени
    """
    if minutes <= 0:
        return "истёк"
    elif minutes < 60:
        return f"{minutes} мин"
    elif minutes < 1440:  # < 24 часов
        hours = minutes // 60
        mins = minutes % 60
        if mins > 0:
            return f"{hours}ч {mins}м"
        return f"{hours}ч"
    else:  # >= 24 часов
        days = minutes // 1440
        hours = (minutes % 1440) // 60
        if hours > 0:
            return f"{days}д {hours}ч"
        return f"{days}д"


def get_stats_keyboard():
    """Клавиатура для статистики"""
    ikb = InlineKeyboardBuilder()
    ikb.button(text="🔄 Обновить", callback_data="stats:refresh")
    ikb.button(text="📊 Детали", callback_data="stats:details")
    ikb.button(text="🏆 Топ-спамеры", callback_data="stats:top_spammers")
    ikb.button(text="🔤 Топ-слова", callback_data="stats:top_words")
    ikb.button(text="🚀 Назад", callback_data="start")
    ikb.adjust(2, 2, 1)
    return ikb.as_markup()


# ================= ОСНОВНАЯ СТАТИСТИКА =================

@router.callback_query(F.data == "stats:refresh")
@router.callback_query(F.data == "stats")
@router.message(Command(*COMMANDS.get("stats", ["stats"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin())
@log_action(action_name="VIEW_STATS")
async def stats_cmd(update: Message | CallbackQuery) -> None:
    """
    Показывает общую статистику работы бота.

    Включает:
    - Общее количество удалений
    - Активные режимы
    - Статистику банвордов
    - Топ спамеров

    Использование: /stats
    """
    # Определяем тип update
    if isinstance(update, CallbackQuery):
        message = update.message
        is_callback = True
    else:
        message = update
        is_callback = False

    manager = get_manager()

    try:
        # Получаем данные
        stats = await manager.get_stats()
        data = await manager.get_all_words_list()
        top_spammers = await manager.get_top_spammers(limit=5)

        # Проверяем активные режимы
        is_silence = await manager.is_silence_active()
        is_conflict = await manager.is_conflict_active()

        # === ФОРМИРУЕМ ВЫВОД ===

        output = "📊 <b>СТАТИСТИКА PRIMOGUARD</b>\n\n"

        # Общая информация
        total_deletions = stats.get('total_deletions', 0)
        output += f"🗑 <b>Всего удалений:</b> <code>{format_number(total_deletions)}</code>\n\n"

        # Активные режимы
        if is_silence or is_conflict:
            output += "🔴 <b>АКТИВНЫЕ РЕЖИМЫ:</b>\n\n"

            if is_silence:
                silence_until_str = await manager.repo.get_setting("silence_until")
                silence_until = datetime.fromtimestamp(float(silence_until_str))
                time_left_seconds = (silence_until - datetime.now()).total_seconds()
                time_left_minutes = int(time_left_seconds / 60)

                output += f"🔇 <b>Режим тишины</b>\n"
                output += f"├─ ⏱ Осталось: <code>{format_time_remaining(time_left_minutes)}</code>\n"
                output += f"└─ 🕐 До: {format_datetime(silence_until)}\n"

                if is_conflict:
                    output += "│\n"

            if is_conflict:
                conflict_until_str = await manager.repo.get_setting("conflict_until")
                conflict_until = datetime.fromtimestamp(float(conflict_until_str))
                time_left_seconds = (conflict_until - datetime.now()).total_seconds()
                time_left_minutes = int(time_left_seconds / 60)

                conflict_words_count = len(data.get('conflict_substring', set()))
                conflict_lemmas_count = len(data.get('conflict_lemma', set()))
                total_conflict = conflict_words_count + conflict_lemmas_count

                output += f"⚔️ <b>Режим антиконфликта</b>\n"
                output += f"├─ ⏱ Осталось: <code>{format_time_remaining(time_left_minutes)}</code>\n"
                output += f"├─ 🕐 До: {format_datetime(conflict_until)}\n"
                output += f"└─ 📊 Правил: <code>{total_conflict}</code>\n"

            output += "\n"

        # Статистика правил
        total_rules = (
                len(data.get('substring', set())) +
                len(data.get('lemma', set())) +
                len(data.get('part', set())) +
                len(data.get('temp_substring', set())) +
                len(data.get('temp_lemma', set())) +
                len(data.get('conflict_substring', set())) +
                len(data.get('conflict_lemma', set()))
        )

        output += f"📋 <b>Правила модерации:</b>\n"
        output += f"├─ Всего правил: <code>{total_rules}</code>\n"
        output += f"├─ Постоянные: <code>{len(data.get('substring', set())) + len(data.get('lemma', set())) + len(data.get('part', set()))}</code>\n"
        output += f"├─ Временные: <code>{len(data.get('temp_substring', set())) + len(data.get('temp_lemma', set()))}</code>\n"
        output += f"├─ Конфликтные: <code>{len(data.get('conflict_substring', set())) + len(data.get('conflict_lemma', set()))}</code>\n"
        output += f"└─ Исключения: <code>{len(data.get('whitelist', set()))}</code>\n\n"

        # Топ-5 спамеров
        if top_spammers:
            output += "🏆 <b>Топ-5 спамеров:</b>\n"
            max_count = top_spammers[0][1] if top_spammers else 1

            for idx, (user_id, count) in enumerate(top_spammers, 1):
                bar = create_text_bar(count, max_count, length=8)
                output += f'{idx}. <a href="tg://user?id={user_id}">{user_id}</a> — {count} [{bar}]\n'

            output += "\n"
        else:
            output += "🏆 <b>Топ-5 спамеров:</b>\n"
            output += "└─ <i>Нет данных</i>\n\n"

        # Администраторы
        admins_count = len(settings.OWNER_ID) + len(data.get('admins', set()))
        output += f"👥 <b>Администраторов:</b> <code>{admins_count}</code>\n\n"

        # Подсказка
        output += "💡 <i>Используйте кнопки для детальной информации</i>"

        # Клавиатура
        keyboard = get_stats_keyboard()

        # Отправка
        if is_callback:
            await message.edit_text(
                text=output,
                parse_mode="HTML",
                reply_markup=keyboard
            )
            await update.answer("✅ Статистика обновлена")
        else:
            await message.answer(
                text=output,
                parse_mode="HTML",
                reply_markup=keyboard
            )

    except Exception as e:
        logger.error(f"Ошибка получения статистики: {e}", log_type="STATS")

        error_text = "❌ <b>Ошибка загрузки статистики</b>\n\nПопробуйте позже"

        if is_callback:
            await update.answer("❌ Ошибка загрузки", show_alert=True)
        else:
            await message.answer(error_text, parse_mode="HTML")


# ================= ДЕТАЛЬНАЯ СТАТИСТИКА =================

@router.callback_query(F.data == "stats:details")
@log_action(action_name="VIEW_DETAILED_STATS")
async def stats_details_callback(callback: CallbackQuery) -> None:
    """Показывает детальную статистику"""
    manager = get_manager()

    try:
        stats = await manager.get_stats()
        data = await manager.get_all_words_list()

        output = "📊 <b>ДЕТАЛЬНАЯ СТАТИСТИКА</b>\n\n"

        # Подробная статистика удалений
        total_deletions = stats.get('total_deletions', 0)
        output += f"🗑 <b>Удаления сообщений:</b>\n"
        output += f"├─ Всего: <code>{format_number(total_deletions)}</code>\n"
        output += "\n"

        # Активные режимы (детально)
        is_silence = await manager.is_silence_active()
        is_conflict = await manager.is_conflict_active()

        if is_silence or is_conflict:
            output += "🔴 <b>Активные режимы:</b>\n\n"

            if is_silence:
                silence_until_str = await manager.repo.get_setting("silence_until")
                silence_until = datetime.fromtimestamp(float(silence_until_str))
                time_left_seconds = (silence_until - datetime.now()).total_seconds()
                time_left_minutes = int(time_left_seconds / 60)

                output += f"🔇 <b>Режим тишины:</b>\n"
                output += f"├─ Статус: ✅ Активен\n"
                output += f"├─ Осталось: <code>{format_time_remaining(time_left_minutes)}</code>\n"
                output += f"├─ Окончание: {format_datetime(silence_until)}\n"
                output += f"└─ Эффект: Удаляются ВСЕ сообщения\n\n"

            if is_conflict:
                conflict_until_str = await manager.repo.get_setting("conflict_until")
                conflict_until = datetime.fromtimestamp(float(conflict_until_str))
                time_left_seconds = (conflict_until - datetime.now()).total_seconds()
                time_left_minutes = int(time_left_seconds / 60)

                conflict_words_count = len(data.get('conflict_substring', set()))
                conflict_lemmas_count = len(data.get('conflict_lemma', set()))

                output += f"⚔️ <b>Режим антиконфликта:</b>\n"
                output += f"├─ Статус: ✅ Активен\n"
                output += f"├─ Осталось: <code>{format_time_remaining(time_left_minutes)}</code>\n"
                output += f"├─ Окончание: {format_datetime(conflict_until)}\n"
                output += f"├─ Слов: <code>{conflict_words_count}</code>\n"
                output += f"├─ Лемм: <code>{conflict_lemmas_count}</code>\n"
                output += f"└─ Эффект: Обычные банворды отключены\n\n"

        # Детальная статистика правил
        output += f"📋 <b>Правила модерации:</b>\n\n"

        output += f"🔴 <b>Постоянные:</b>\n"
        output += f"├─ Подстроки: <code>{len(data.get('substring', set()))}</code>\n"
        output += f"├─ Леммы: <code>{len(data.get('lemma', set()))}</code>\n"
        output += f"└─ Части: <code>{len(data.get('part', set()))}</code>\n\n"

        output += f"⏱ <b>Временные:</b>\n"
        output += f"├─ Подстроки: <code>{len(data.get('temp_substring', set()))}</code>\n"
        output += f"└─ Леммы: <code>{len(data.get('temp_lemma', set()))}</code>\n\n"

        output += f"⚔️ <b>Конфликтные:</b>\n"
        output += f"├─ Слова: <code>{len(data.get('conflict_substring', set()))}</code>\n"
        output += f"└─ Леммы: <code>{len(data.get('conflict_lemma', set()))}</code>\n\n"

        output += f"✅ <b>Исключения:</b> <code>{len(data.get('whitelist', set()))}</code>\n\n"

        # Информация о кэше
        cache_info = stats.get('cache_active', False)
        cache_updated = stats.get('cache_updated_at', None)

        output += f"💾 <b>Кэш:</b>\n"
        output += f"├─ Статус: {'✅ Активен' if cache_info else '❌ Неактивен'}\n"

        if cache_updated and isinstance(cache_updated, str):
            try:
                updated_dt = datetime.fromisoformat(cache_updated)
                output += f"└─ Обновлён: {format_datetime(updated_dt)}\n"
            except (ValueError, TypeError):
                output += f"└─ Обновлён: недавно\n"
        else:
            output += f"└─ Не обновлялся\n"

        # Кнопка возврата
        ikb = InlineKeyboardBuilder()
        ikb.button(text="◀️ Назад", callback_data="stats:refresh")

        await callback.message.edit_text(
            text=output,
            parse_mode="HTML",
            reply_markup=ikb.as_markup()
        )
        await callback.answer()

    except Exception as e:
        logger.error(f"Ошибка получения детальной статистики: {e}", log_type="STATS")
        await callback.answer("❌ Ошибка загрузки", show_alert=True)


# ================= ТОП СПАМЕРОВ =================

@router.callback_query(F.data == "stats:top_spammers")
@log_action(action_name="VIEW_TOP_SPAMMERS")
async def stats_top_spammers_callback(callback: CallbackQuery) -> None:
    """Показывает топ-10 спамеров"""
    manager = get_manager()

    try:
        top_spammers = await manager.get_top_spammers(limit=10)

        output = "🏆 <b>ТОП-10 СПАМЕРОВ</b>\n\n"

        if top_spammers:
            max_count = top_spammers[0][1] if top_spammers else 1

            for idx, (user_id, count) in enumerate(top_spammers, 1):
                bar = create_text_bar(count, max_count, length=10)

                # Эмодзи для топ-3
                if idx == 1:
                    medal = "🥇"
                elif idx == 2:
                    medal = "🥈"
                elif idx == 3:
                    medal = "🥉"
                else:
                    medal = f"{idx}."

                output += f'{medal} <a href="tg://user?id={user_id}">{user_id}</a>\n'
                output += f"   └─ {format_number(count)} удалений [{bar}]\n\n"

            # Общая статистика
            total_spammers = len(top_spammers)
            total_deletions = sum(count for _, count in top_spammers)

            output += f"📊 <b>Статистика:</b>\n"
            output += f"├─ Всего пользователей: <code>{total_spammers}</code>\n"
            output += f"└─ Всего удалений: <code>{format_number(total_deletions)}</code>\n\n"

            output += "💡 <i>ID можно использовать для проверки пользователя</i>"
        else:
            output += "└─ <i>Нет данных об удалениях</i>\n\n"
            output += "💡 <i>Когда бот начнёт удалять сообщения, здесь появится статистика</i>"

        # Кнопка возврата
        ikb = InlineKeyboardBuilder()
        ikb.button(text="◀️ Назад", callback_data="stats:refresh")

        await callback.message.edit_text(
            text=output,
            parse_mode="HTML",
            reply_markup=ikb.as_markup()
        )
        await callback.answer()

    except Exception as e:
        logger.error(f"Ошибка получения топ спамеров: {e}", log_type="STATS")
        await callback.answer("❌ Ошибка загрузки", show_alert=True)


# ================= ТОП СЛОВ =================

@router.callback_query(F.data == "stats:top_words")
async def stats_top_words_callback(callback: CallbackQuery) -> None:
    """Показывает топ-10 самых частых срабатываний"""
    await callback.answer()

    manager = get_manager()

    # Получаем топ слов
    top_words = await manager.get_top_words(limit=10)

    if not top_words:
        text = (
            "🔤 <b>ТОП-10 СРАБАТЫВАНИЙ ПО СЛОВАМ</b>\n\n"
            "📭 <i>Статистика пока пуста</i>\n\n"
            "Срабатывания появятся после удаления\n"
            "первых спам-сообщений."
        )
    else:
        text = "🔤 <b>ТОП-10 СРАБАТЫВАНИЙ ПО СЛОВАМ</b>\n\n"

        # Эмодзи для типов
        type_emoji = {
            "substring": "🔤",
            "lemma": "📖",
            "part": "🧩",
            "silence": "🔇",
            "conflict_substring": "⚔️",
            "conflict_lemma": "⚔️"
        }

        for i, word_data in enumerate(top_words, 1):
            word = word_data['word']
            count = word_data['count']
            word_type = word_data['type']
            emoji = type_emoji.get(word_type, "❓")

            # Медали для топ-3
            medal = ""
            if i == 1:
                medal = "🥇 "
            elif i == 2:
                medal = "🥈 "
            elif i == 3:
                medal = "🥉 "

            text += f"{medal}<b>{i}.</b> {emoji} <code>{word}</code> — {count} раз\n"

        # Общая статистика
        total = await manager.get_total_spam_count()
        text += f"\n📊 <b>Всего удалено:</b> {total} сообщений"

    # Кнопка назад
    keyboard = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="◀️ Назад", callback_data="stats:refresh")]
    ])

    try:
        await callback.message.edit_text(
            text=text,
            reply_markup=keyboard,
            parse_mode="HTML"
        )
    except Exception as e:
        logger.error(f"Ошибка показа топ-слов: {e}", log_type="ERROR")
        await callback.answer("❌ Ошибка загрузки статистики", show_alert=True)


# ================= СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ =================

@router.message(Command(*COMMANDS.get("userstats", ["userstats"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin())
@log_action(action_name="VIEW_USER_STATS", log_args=True)
async def user_stats_cmd(message: Message) -> None:
    """
    Показывает статистику конкретного пользователя.

    Использование: /userstats <ID>
    Пример: /userstats 123456789
    """
    parts = message.text.split(maxsplit=1)

    if len(parts) < 2:
        await message.answer(
            "❌ Использование: <code>/userstats [ID]</code>\n\n"
            "Пример: <code>/userstats 123456789</code>",
            parse_mode="HTML"
        )
        return

    try:
        user_id = int(parts[1].strip())
    except ValueError:
        await message.answer("❌ ID должен быть числом", parse_mode="HTML")
        return

    manager = get_manager()

    try:
        # Получаем статистику пользователя
        user_spam_count = await manager.get_user_spam_count(user_id)
        user_spam_stats = await manager.get_spam_stats(limit=10, user_id=user_id)

        output = f"👤 <b>СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ</b>\n\n"
        output += f'🆔 ID: <a href="tg://user?id={user_id}">{user_id}</a>\n\n'

        if user_spam_count > 0:
            output += f"🗑 <b>Удалено сообщений:</b> <code>{format_number(user_spam_count)}</code>\n\n"

            if user_spam_stats:
                output += f"📝 <b>Последние удаления:</b>\n"

                for stat in user_spam_stats[:5]:
                    deleted_at = stat.deleted_at
                    matched_word = stat.matched_word or "неизвестно"
                    match_type = stat.match_type or "unknown"

                    output += f"├─ {format_datetime(deleted_at)}\n"
                    output += f"│  └─ Слово: <code>{matched_word}</code> ({match_type})\n"

                output += "\n"
        else:
            output += "✅ <i>Нет нарушений</i>\n\n"
            output += "Этот пользователь не нарушал правила чата"

        await message.answer(output, parse_mode="HTML")

    except Exception as e:
        logger.error(f"Ошибка получения статистики пользователя: {e}", log_type="STATS")
        await message.answer("❌ <b>Ошибка загрузки статистики</b>", parse_mode="HTML")


# ================= СБРОС СТАТИСТИКИ =================

@router.message(Command(*COMMANDS.get("resetstats", ["resetstats"]), prefix=settings.PREFIX, ignore_case=True),
                IsAdmin())
@log_action(action_name="RESET_STATS")
async def reset_stats_cmd(message: Message) -> None:
    """
    Сбрасывает всю статистику удалений.

    ⚠️ ВНИМАНИЕ: Это действие необратимо!

    Использование: /resetstats confirm
    """
    parts = message.text.split(maxsplit=1)

    if len(parts) < 2 or parts[1].lower() != "confirm":
        await message.answer(
            "⚠️ <b>ВНИМАНИЕ!</b>\n\n"
            "Эта команда удалит ВСЮ статистику удалений:\n"
            "• Счётчики удалений пользователей\n"
            "• Историю удалённых сообщений\n"
            "• Топ спамеров\n\n"
            "Правила модерации НЕ будут удалены.\n\n"
            "Для подтверждения используйте:\n"
            "<code>/resetstats confirm</code>",
            parse_mode="HTML"
        )
        return

    manager = get_manager()

    try:
        # Сбрасываем статистику
        deleted_count = await manager.reset_spam_stats()

        if deleted_count > 0:
            await message.answer(
                f"✅ <b>Статистика сброшена</b>\n\n"
                f"Удалено записей: {deleted_count}\n\n"
                f"Новые данные начнут собираться\n"
                f"с этого момента.",
                parse_mode="HTML"
            )
            logger.warning(
                f"Статистика сброшена пользователем {message.from_user.id}: "
                f"удалено {deleted_count} записей",
                log_type="STATS"
            )
        else:
            await message.answer(
                "ℹ️ <b>Статистика уже пуста</b>",
                parse_mode="HTML"
            )

    except Exception as e:
        logger.error(f"Ошибка сброса статистики: {e}", log_type="STATS")
        await message.answer("❌ <b>Ошибка сброса статистики</b>", parse_mode="HTML")

