"""
Мониторинг чата
Считывает все сообщения для статистики и детекта шпионов
"""
import logging
from datetime import datetime
from aiogram import Router, F
from aiogram.types import Message
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database.db import AsyncSessionLocal
from database.models import User, Message as MessageModel, SpamWarning
from services.spy_detector import SpyDetector
from services.antispam import AntiSpamService
import config

logger = logging.getLogger(__name__)

router = Router()

# Баллы за активность
RATING_PER_MESSAGE = 1  # +1 балл за каждое сообщение


@router.message()
async def monitor_all_messages(message: Message):
    """
    Перехват всех сообщений в чате
    Для статистики и анализа
    """
    # Пропускаем сообщения от ботов
    if message.from_user.is_bot:
        return

    # Пропускаем сервисные сообщения (в aiogram 3.x нет message.system)
    if message.chat.type != 'private' and hasattr(message, 'is_topic_closed'):
        # Это сообщение из темы форума — пропускаем служебные
        pass

    user_id = message.from_user.id
    chat_id = message.chat.id
    text = message.text or ''

    async with AsyncSessionLocal() as session:
        # Получаем или создаём пользователя
        stmt = select(User).where(User.user_id == user_id)
        result = await session.execute(stmt)
        user = result.scalar_one_or_none()

        if not user:
            # Создаём нового пользователя
            user = User(
                user_id=user_id,
                username=message.from_user.username,
                first_name=message.from_user.first_name,
                last_name=message.from_user.last_name,
            )
            session.add(user)
        else:
            # Логируем изменения профиля
            from database.models import ProfileHistory
            
            changes = []
            
            if user.username != message.from_user.username:
                changes.append(('username', user.username, message.from_user.username))
                user.username = message.from_user.username
            
            if user.first_name != message.from_user.first_name:
                changes.append(('first_name', user.first_name, message.from_user.first_name))
                user.first_name = message.from_user.first_name
            
            if user.last_name != message.from_user.last_name:
                changes.append(('last_name', user.last_name, message.from_user.last_name))
                user.last_name = message.from_user.last_name
            
            # Сохраняем историю изменений
            for field_name, old_value, new_value in changes:
                history_record = ProfileHistory(
                    user_id=user_id,
                    field_name=field_name,
                    old_value=old_value,
                    new_value=new_value,
                )
                session.add(history_record)
                
                if old_value:
                    logger.info(f'Profile change: user_id={user_id}, {field_name}: {old_value} → {new_value}')

        # Обновляем данные (защищаемся от None)
        user.message_count = (user.message_count or 0) + 1
        user.last_seen = datetime.utcnow()

        # Начисляем рейтинг за сообщение (защищаемся от None)
        user.rating = (user.rating or 0) + RATING_PER_MESSAGE
        user.update_level()  # Обновляем уровень

        # ==========================================
        # ПРОВЕРКА ДОСТИЖЕНИЙ
        # ==========================================
        if not config.is_admin(user_id):
            from services.achievements import AchievementsService
            achievements_service = AchievementsService(session)
            
            # Проверяем и выдаём достижения
            awarded = await achievements_service.check_and_award(
                user_id,
                message_count=user.message_count,
                rating=user.rating,
                message_hour=datetime.utcnow().hour
            )
            
            # Уведомляем о полученных достижениях
            for ach_type in awarded:
                ach_info = achievements_service.get_achievement_info(ach_type)
                try:
                    await message.bot.send_message(
                        user_id,
                        f'🏆 <b>Новое достижение!</b>\n\n'
                        f'{ach_info.get("emoji", "🏆")} <b>{ach_info.get("name", ach_type)}</b>\n\n'
                        f'{ach_info.get("description", "")}\n\n'
                        f'Продолжайте в том же духе!',
                        parse_mode='HTML'
                    )
                    logger.info(f'Пользователь {user_id} получил достижение {ach_type}')
                except Exception as e:
                    logger.error(f'Не удалось уведомить о достижении: {e}')

        # ==========================================
        # ПРОВЕРКА НА СПАМ (чёрный список ссылок)
        # ==========================================
        if text and not config.is_admin(user_id):
            antispam = AntiSpamService(session)
            is_spam, found_items, reason = antispam.check_message(text)
            settings = antispam.get_settings()

            if is_spam:
                # Сохраняем предупреждение
                spam_warning = SpamWarning(
                    user_id=user_id,
                    message_text=text[:1000] if text else None,
                    reason=reason,
                )
                session.add(spam_warning)

                # Увеличиваем счётчик предупреждений
                user.spam_warning_count += 1
                warning_count = user.spam_warning_count

                # Получаем настройки
                delete_message = settings.get('delete_message', True)
                warn_user = settings.get('warn_user', True)
                notify_admin = settings.get('notify_admin', True)
                ban_after = settings.get('ban_after_warnings', 3)

                # Удаляем сообщение если нужно
                if delete_message:
                    try:
                        await message.delete()
                        logger.info(f'Спам удалён от user_id={user_id}: {reason}')
                    except Exception as e:
                        logger.error(f'Не удалось удалить спам: {e}')

                # Предупреждаем пользователя
                if warn_user:
                    try:
                        await message.bot.send_message(
                            user_id,
                            f'⚠️ <b>Предупреждение #{warning_count}</b>\n\n'
                            f'В вашем сообщении обнаружена запрещённая ссылка или спам.\n\n'
                            f'Причина: {reason}\n\n'
                            f'📊 Ваши нарушения: {warning_count} из {ban_after}\n\n'
                            f'При следующем нарушении будет публичное предупреждение.\n'
                            f'При достижении {ban_after} предупреждений — бан.',
                            parse_mode='HTML'
                        )
                    except Exception as e:
                        logger.error(f'Не удалось предупредить пользователя: {e}')

                # Уведомляем админа
                if notify_admin:
                    try:
                        await message.bot.send_message(
                            config.ADMIN_USER_ID,
                            f'⚠️ <b>СПАМ В ЧАТЕ!</b>\n\n'
                            f'Пользователь: {user.full_name}\n'
                            f'ID: <code>{user.user_id}</code>\n'
                            f'Квартира: {user.apartment or "не указана"}\n\n'
                            f'Причина: {reason}\n\n'
                            f'Предупреждений: {warning_count} из {ban_after}',
                            parse_mode='HTML'
                        )
                    except Exception as e:
                        logger.error(f'Не удалось уведомить админа о спаме: {e}')

                # Бан после достижения лимита
                if warning_count >= ban_after:
                    user.is_banned = True
                    try:
                        await message.bot.send_message(
                            user_id,
                            f'🚫 <b>ВЫ ЗАБАНЕНЫ</b>\n\n'
                            f'Причина: Систематический спам ({warning_count} предупреждений).\n\n'
                            f'Вы больше не можете писать в чат.',
                            parse_mode='HTML'
                        )
                        # Пытаемся удалить из чата
                        await message.bot.ban_chat_member(chat_id, user_id)
                    except Exception as e:
                        logger.error(f'Не удалось забанить спамера: {e}')

                    logger.warning(f'Пользователь {user_id} забанен за спам')

                await session.commit()

                # Прерываем дальнейшую обработку если спам
                return

        # ==========================================
        # ПРОВЕРКА ЛИМИТОВ СООБЩЕНИЙ (анти-спам)
        # ==========================================
        if not config.is_admin(user_id):
            from services.rate_limiter import RateLimiter
            rate_limiter = RateLimiter(session)
            
            # Проверяем не замучен ли пользователь
            if user.is_muted and user.mute_until:
                # Проверяем истёк ли мут
                if await rate_limiter.check_mute_expired(user_id):
                    # Мут истёк — пропускаем сообщение
                    pass
                else:
                    # Ещё замучен — удаляем сообщение
                    try:
                        await message.delete()
                        logger.info(f'Сообщение от замученного user_id={user_id} удалено')
                    except Exception as e:
                        logger.error(f'Не удалось удалить сообщение замученного: {e}')
                    return

            # Проверяем лимиты
            is_limited, msg_count = await rate_limiter.check_rate_limit(user_id)
            
            if is_limited:
                # Добавляем сообщение в счётчик (для статистики)
                await rate_limiter.add_message(user_id)
                
                # Увеличиваем предупреждения
                user.rate_limit_warnings += 1
                warning_count = user.rate_limit_warnings
                
                config_rl = rate_limiter.get_config()
                mute_after = config_rl.get('warnings_before_mute', 2)
                
                # Удаляем сообщение
                try:
                    await message.delete()
                    logger.info(f'Флуд удалён от user_id={user_id}')
                except Exception as e:
                    logger.error(f'Не удалось удалить флуд: {e}')

                # Предупреждаем пользователя
                try:
                    await message.bot.send_message(
                        user_id,
                        f'⚠️ <b>Предупреждение #{warning_count}</b>\n\n'
                        f'Вы превысили лимит сообщений!\n\n'
                        f'📊 Ваши нарушения: {warning_count} из {mute_after}\n\n'
                        f'Лимит: {config_rl["max_messages"]} сообщений за {config_rl["period_seconds"]} сек.\n'
                        f'Вы отправили: {msg_count} сообщ.\n\n'
                        f'При достижении {mute_after} предупреждений вы будете замучены на {config_rl["mute_duration_minutes"]} мин.',
                        parse_mode='HTML'
                    )
                except Exception as e:
                    logger.error(f'Не удалось предупредить о флуде: {e}')

                # Уведомляем админа
                try:
                    await message.bot.send_message(
                        config.ADMIN_USER_ID,
                        f'⚠️ <b>ФЛУД В ЧАТЕ!</b>\n\n'
                        f'Пользователь: {user.full_name}\n'
                        f'ID: <code>{user.user_id}</code>\n'
                        f'Квартира: {user.apartment or "не указана"}\n\n'
                        f'Сообщений: {msg_count} (лимит: {config_rl["max_messages"]})\n'
                        f'Предупреждений: {warning_count} из {mute_after}',
                        parse_mode='HTML'
                    )
                except Exception as e:
                    logger.error(f'Не удалось уведомить админа о флуде: {e}')

                # Мут после достижения лимита предупреждений
                if warning_count >= mute_after:
                    mute_until = await rate_limiter.mute_user(user_id)
                    
                    try:
                        await message.bot.send_message(
                            user_id,
                            f'🔇 <b>ВЫ ЗАМУЧЕНЫ</b>\n\n'
                            f'Причина: Превышение лимита сообщений ({warning_count} предупреждений).\n\n'
                            f'Мут до: {mute_until.strftime("%d.%m.%Y %H:%M")}\n\n'
                            f'Вы не сможете писать в чат до указанного времени.',
                            parse_mode='HTML'
                        )
                    except Exception as e:
                        logger.error(f'Не удалось уведомить о муте: {e}')

                    logger.warning(f'Пользователь {user_id} замучен за флуд')

                await session.commit()
                return

            # Добавляем сообщение в счётчик (если не превышен лимит)
            await rate_limiter.add_message(user_id)

        # Классифицируем тему сообщения
        topic = None
        if text:
            from services.topics_analyzer import TopicsAnalyzer
            topics_analyzer = TopicsAnalyzer(session)
            topic = await topics_analyzer.analyze_message(text)

        # Анализируем токсичность сообщения
        toxicity_score = 0
        if text and not config.is_admin(user_id):
            from services.toxicity_detector import ToxicityDetector
            toxicity_detector = ToxicityDetector(session)
            toxicity_score, _ = await toxicity_detector.analyze_message(text)

            # Обновляем статистику пользователя
            if toxicity_score > 0:
                user.toxic_messages_count += 1
                # Обновляем средний score
                total_messages = user.message_count + 1
                user.toxicity_score = int(
                    (user.toxicity_score * (total_messages - 1) + toxicity_score) / total_messages
                )

                # Уведомляем админа если токсичность высокая
                if toxicity_score > 50:
                    try:
                        await message.bot.send_message(
                            config.ADMIN_USER_ID,
                            f'⚠️ <b>Токсичное сообщение!</b>\n\n'
                            f'Пользователь: {user.full_name}\n'
                            f'ID: <code>{user.user_id}</code>\n'
                            f'Квартира: {user.apartment or "не указана"}\n'
                            f'Toxicity Score: {toxicity_score}/100\n\n'
                            f'Проверьте через /toxic_stats {user.user_id}',
                            parse_mode='HTML'
                        )
                    except Exception as e:
                        logger.error(f'Не удалось уведомить о токсичности: {e}')

        # Сохраняем сообщение (если не спам)
        msg_model = MessageModel(
            message_id=message.message_id,
            user_id=user_id,
            chat_id=chat_id,
            text=text[:4000] if text else None,
            topic=topic,  # Сохраняем тему
            reply_to_message_id=message.reply_to_message.message_id if message.reply_to_message else None,
        )
        session.add(msg_model)

        await session.commit()

        # Проверяем на шпиона (только если не админ)
        if not config.is_admin(user_id) and config.SPY_DETECTION_ENABLED:
            spy_detector = SpyDetector(session)
            changed = await spy_detector.update_spy_score(user)

            # Если score стал критическим — уведомляем админа
            if user.spy_score > 60 and changed:
                try:
                    await message.bot.send_message(
                        config.get_admin_chat_id(),
                        f'🚨 <b>ВНИМАНИЕ! ВОЗМОЖНЫЙ ШПИОН!</b>\n\n'
                        f'Пользователь: {user.full_name}\n'
                        f'ID: <code>{user.user_id}</code>\n'
                        f'Квартира: {user.apartment or "не указана"}\n'
                        f'Spy Score: {user.spy_score}/100\n\n'
                        f'Флаги: {user.spy_flags}',
                        parse_mode='HTML'
                    )
                except Exception as e:
                    logger.error(f'Не удалось уведомить о шпионе: {e}')

        logger.debug(f"User {user_id}: msg_count={user.message_count}, rating={user.rating}, level={user.level}")
