"""
Хендлер верификации жильцов
"""
import logging
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery
from aiogram.filters import Command
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database.db import AsyncSessionLocal
from database.models import User, VerificationRequest
from utils.validators import validate_apartment
from utils.decorators import admin_only, admin_callback_only
import config
from datetime import datetime

logger = logging.getLogger(__name__)

router = Router()


@router.message(Command('верификация'))
@router.message(Command('verification'))
async def cmd_verification(message: Message):
    """Команда /верификация - статус верификации"""
    logger.info(f'Команда /верификация от user_id={message.from_user.id}')
    
    async with AsyncSessionLocal() as session:
        stmt = select(User).where(User.user_id == message.from_user.id)
        result = await session.execute(stmt)
        user = result.scalar_one_or_none()
        
        if not user:
            await message.answer(
                '❌ Вы не зарегистрированы.\n\n'
                'Нажмите /start или отправьте номер квартиры.'
            )
            return
        
        if user.verified:
            await message.answer(
                f'✅ Вы верифицированы\n\n'
                f'Квартира: <code>{user.apartment}</code>\n'
                f'Сообщений: {user.message_count}',
                parse_mode='HTML'
            )
        else:
            # Проверяем, есть ли заявка
            stmt = select(VerificationRequest).where(
                VerificationRequest.user_id == message.from_user.id,
                VerificationRequest.status == 'pending'
            )
            result = await session.execute(stmt)
            request = result.scalar_one_or_none()
            
            if request:
                await message.answer(
                    f'⏳ <b>Заявка на проверке</b>\n\n'
                    f'Квартира: <code>{request.apartment}</code>\n'
                    f'Статус: Ожидает подтверждения\n\n'
                    f'Администратор скоро подтвердит вашу заявку.',
                    parse_mode='HTML'
                )
            else:
                await message.answer(
                    f'⏳ Вы не верифицированы\n\n'
                    f'📝 <b>Как пройти верификацию:</b>\n\n'
                    f'1. Отправьте номер квартиры текстом\n'
                    f'2. Дождитесь подтверждения администратора\n\n'
                    f'Примеры: <code>45</code>, <code>12А</code>, <code>100-1</code>',
                    parse_mode='HTML'
                )


@router.message(F.text.regexp(r'^\s*\d+[А-ЯA-Z]?[\s/-]?\d*[А-ЯA-Z]?\s*$'))
async def handle_apartment_number(message: Message):
    """
    Обработка номера квартиры
    Срабатывает и в личке, и в группе
    """
    text = message.text.strip()
    user_id = message.from_user.id
    
    # Если админ отправил номер квартиры — автоматически верифицируем
    if config.is_admin(user_id):
        logger.info(f'Админ отправил номер квартиры: {text}, автоматически верифицируем')
        await auto_verify_admin(message, text)
        return
    
    logger.info(f'Получен номер квартиры: {text} от user_id={user_id}')
    
    # Проверяем валидность
    if not validate_apartment(text):
        logger.info(f'Неверный формат квартиры: {text}')
        return  # Просто игнорируем, это не номер квартиры
    
    await process_verification(message, text)


async def auto_verify_admin(message: Message, apartment: str):
    """Автоматическая верификация админа"""
    user_id = message.from_user.id
    apartment_upper = apartment.strip().upper()
    
    async with AsyncSessionLocal() as session:
        try:
            # Проверяем пользователя в БД
            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,
                    apartment=apartment_upper,
                    verified=True,
                    is_admin=True,
                    verification_date=datetime.utcnow(),
                )
                session.add(user)
                logger.info(f'Создан новый админ с квартирой {apartment_upper}')
            else:
                # Обновляем данные админа
                user.apartment = apartment_upper
                user.verified = True
                user.is_admin = True
                if not user.verification_date:
                    user.verification_date = datetime.utcnow()
                logger.info(f'Админ верифицирован с квартирой {apartment_upper}')
            
            await session.commit()
            
            await message.answer(
                f'✅ <b>Администратор верифицирован!</b>\n\n'
                f'Квартира: <code>{apartment_upper}</code>\n'
                f'Статус: <b>Владелец/Админ</b>\n\n'
                f'Теперь вы можете использовать все админские функции.',
                parse_mode='HTML'
            )
            
        except Exception as e:
            logger.error(f'Ошибка при авто-верификации админа: {e}', exc_info=True)
            await message.answer('❌ Произошла ошибка при верификации админа.')


@router.message(F.text, F.chat.type == 'private')
async def handle_any_text_in_private(message: Message):
    """
    Обработка любого текста в личке
    Пытаемся распознать номер квартиры
    """
    # Пропускаем если это админ
    if config.is_admin(message.from_user.id):
        return
    
    text = message.text.strip()
    logger.info(f'Текст в личке: {text} от user_id={message.from_user.id}')
    
    # Проверяем, похоже ли на номер квартиры
    if validate_apartment(text):
        logger.info(f'Распознан номер квартиры: {text}')
        await process_verification(message, text)
    else:
        # Если не похоже на квартиру — подсказываем
        logger.info(f'Не похоже на номер квартиры: {text}')
        # Не отвечаем на каждое сообщение, чтобы не спамить


async def process_verification(message: Message, apartment: str):
    """Обработка верификации"""
    user_id = message.from_user.id
    apartment_upper = apartment.strip().upper()
    
    logger.info(f'Начало верификации: user_id={user_id}, apartment={apartment_upper}')
    
    async with AsyncSessionLocal() as session:
        try:
            # Проверяем пользователя в БД
            stmt = select(User).where(User.user_id == user_id)
            result = await session.execute(stmt)
            user = result.scalar_one_or_none()
            
            if not user:
                logger.info(f'Создаём нового пользователя: user_id={user_id}')
                # Создаём нового пользователя
                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,
                    apartment=apartment_upper,
                )
                session.add(user)
            else:
                logger.info(f'Пользователь найден: verified={user.verified}, apartment={user.apartment}')
                
                # Если уже верифицирован
                if user.verified:
                    # Но квартиры нет — сохраняем!
                    if not user.apartment:
                        user.apartment = apartment_upper
                        await session.commit()
                        logger.info(f'Сохранена квартира для верифицированного: {apartment_upper}')
                        
                        await message.answer(
                            f'✅ <b>Квартира сохранена!</b>\n\n'
                            f'Квартира: <code>{apartment_upper}</code>\n\n'
                            f'Вы уже были верифицированы.\n'
                            f'Теперь ваша квартира привязана к аккаунту!',
                            parse_mode='HTML'
                        )
                        return
                    else:
                        # Уже есть квартира
                        await message.answer(
                            f'✅ Вы уже верифицированы (кв. {user.apartment})\n\n'
                            'Если нужно изменить квартиру, обратитесь к администратору.',
                            parse_mode='HTML'
                        )
                        return

                # Обновляем квартиру для неверифицированных
                user.apartment = apartment_upper
            
            # Создаём заявку на верификацию (если ещё нет активной)
            stmt = select(VerificationRequest).where(
                VerificationRequest.user_id == user_id,
                VerificationRequest.status == 'pending'
            )
            result = await session.execute(stmt)
            existing_request = result.scalar_one_or_none()
            
            if not existing_request:
                logger.info(f'Создаём заявку на верификацию')
                verification = VerificationRequest(
                    user_id=user_id,
                    apartment=apartment_upper,
                )
                session.add(verification)
            
            await session.commit()
            logger.info(f'Верификация сохранена в БД')
            
            # Уведомляем пользователя
            await message.answer(
                f'✅ <b>Заявка на верификацию создана!</b>\n\n'
                f'Квартира: <code>{apartment_upper}</code>\n'
                f'Статус: На проверке\n\n'
                f'Администратор проверит данные в ближайшее время.\n'
                f'После подтверждения вы получите доступ ко всем функциям.',
                parse_mode='HTML'
            )
            
            # Уведомляем админа
            try:
                user_name = message.from_user.first_name
                username = f'@{message.from_user.username}' if message.from_user.username else 'нет'
                
                await message.bot.send_message(
                    config.ADMIN_USER_ID,
                    f'🔔 <b>Новая заявка на верификацию</b>\n\n'
                    f'Жилец: {user_name} {username}\n'
                    f'Квартира: {apartment_upper}\n'
                    f'ID: <code>{user_id}</code>\n\n'
                    f'Для подтверждения используйте:\n'
                    f'<code>/verify_approve {user_id}</code>',
                    parse_mode='HTML'
                )
                logger.info(f'Админ уведомлён')
            except Exception as e:
                logger.error(f'Не удалось уведомить админа: {e}')
                
        except Exception as e:
            logger.error(f'Ошибка при верификации: {e}', exc_info=True)
            await message.answer('❌ Произошла ошибка при верификации. Попробуйте позже.')


@router.message(Command('verify'))
@admin_only
async def cmd_verify_list(message: Message):
    """Список заявок на верификацию (админ)"""
    logger.info(f'Админ запросил список заявок')
    
    async with AsyncSessionLocal() as session:
        stmt = (
            select(VerificationRequest)
            .where(VerificationRequest.status == 'pending')
            .order_by(VerificationRequest.created_at)
        )
        result = await session.execute(stmt)
        requests = list(result.scalars().all())
    
    if not requests:
        await message.answer('✅ Все заявки обработаны')
        return
    
    text = f'📋 <b>Заявки на верификацию</b> ({len(requests)}):\n\n'
    
    for req in requests:
        # Получаем имя пользователя
        stmt = select(User).where(User.user_id == req.user_id)
        result = await session.execute(stmt)
        user = result.scalar_one_or_none()
        name = user.full_name if user else f'user{req.user_id}'
        
        text += f'• {name} — кв. {req.apartment}\n'
        text += f'  ID: <code>{req.user_id}</code>\n\n'
    
    text += 'Для подтверждения используйте /verify_approve <ID>'
    
    await message.answer(text, parse_mode='HTML')


@router.message(Command('verify_approve'))
@admin_only
async def cmd_verify_approve(message: Message):
    """Подтверждение верификации (работает и в личке, и в группе)"""
    logger.info(f'Админ подтверждает верификацию в чате типа: {message.chat.type}')
    
    # Парсим ID пользователя из команды
    args = message.text.split()
    if len(args) < 2:
        await message.answer('Использование: /verify_approve <user_id>')
        return
    
    try:
        user_id = int(args[1])
    except ValueError:
        await message.answer('❌ Неверный ID пользователя')
        return
    
    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:
            await message.answer('❌ Пользователь не найден')
            return
        
        # Верифицируем
        user.verified = True
        user.verification_date = datetime.utcnow()
        
        # Обновляем заявку
        stmt = select(VerificationRequest).where(
            VerificationRequest.user_id == user_id,
            VerificationRequest.status == 'pending'
        )
        result = await session.execute(stmt)
        request = result.scalar_one_or_none()
        
        if request:
            request.status = 'approved'
            request.reviewed_at = datetime.utcnow()
            request.reviewed_by = message.from_user.id
        
        await session.commit()
        
        logger.info(f'Пользователь {user_id} верифицирован')
        
        # Уведомляем пользователя (в личку)
        try:
            await message.bot.send_message(
                user_id,
                f'✅ <b>Верификация подтверждена!</b>\n\n'
                f'Квартира: {user.apartment}\n'
                f'Теперь у вас есть доступ ко всем функциям бота.',
                parse_mode='HTML'
            )
        except Exception as e:
            logger.error(f'Не удалось уведомить пользователя: {e}')
        
        # Отвечаем админу (в тот же чат где отправил команду)
        await message.answer(
            f'✅ <b>Пользователь верифицирован!</b>\n\n'
            f'Жилец: {user.full_name}\n'
            f'Квартира: {user.apartment}\n'
            f'ID: <code>{user_id}</code>',
            parse_mode='HTML'
        )


@router.message(Command('verify_reject'))
@admin_only
async def cmd_verify_reject(message: Message):
    """Отклонение верификации"""
    args = message.text.split(maxsplit=2)
    if len(args) < 2:
        await message.answer('Использование: /verify_reject <user_id> [причина]')
        return
    
    try:
        user_id = int(args[1])
    except ValueError:
        await message.answer('❌ Неверный ID пользователя')
        return
    
    reason = args[2] if len(args) > 2 else 'Без указания причины'
    
    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:
            await message.answer('❌ Пользователь не найден')
            return
        
        # Обновляем заявку
        stmt = select(VerificationRequest).where(
            VerificationRequest.user_id == user_id,
            VerificationRequest.status == 'pending'
        )
        result = await session.execute(stmt)
        request = result.scalar_one_or_none()
        
        if request:
            request.status = 'rejected'
            request.reviewed_at = datetime.utcnow()
            request.reviewed_by = message.from_user.id
            request.reject_reason = reason
            await session.commit()
        
        # Уведомляем пользователя
        try:
            await message.bot.send_message(
                user_id,
                f'❌ <b>Верификация отклонена</b>\n\n'
                f'Причина: {reason}\n\n'
                f'Если вы считаете это ошибкой, обратитесь к администратору.'
            )
        except Exception as e:
            logger.error(f'Не удалось уведомить пользователя: {e}')
        
        await message.answer(f'❌ Заявка пользователя отклонена')
