"""
API endpoints для управления MTProto аккаунтами Telegram
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import and_
from pydantic import BaseModel
from datetime import datetime
import logging

from app.db.session import get_db
from app.db.models import User, TelegramMtprotoAccount
from app.api.deps import get_current_user
from app.utils.encryption import encrypt_token
from app.services.telegram_mtproto import get_telegram_client, close_telegram_client
import json
import base64

# Проверяем доступность Pyrogram
try:
    from pyrogram import Client
    PYROGRAM_AVAILABLE = True
except ImportError:
    PYROGRAM_AVAILABLE = False

logger = logging.getLogger(__name__)

router = APIRouter()


class MtprotoAccountCreate(BaseModel):
    name: str
    phone: str  # +79991234567
    api_id: int
    api_hash: str
    is_default: bool = False


class MtprotoAccountOut(BaseModel):
    id: int
    tenant_id: int
    name: str
    phone: str
    username: str | None
    status: str
    is_default: bool
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class MtprotoAccountUpdate(BaseModel):
    name: str | None = None
    is_default: bool | None = None
    status: str | None = None


class AuthCodeRequest(BaseModel):
    code: str | None = None  # Код из Telegram/SMS


@router.post("/mtproto/accounts", response_model=MtprotoAccountOut)
async def create_mtproto_account(
    data: MtprotoAccountCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Создать новый MTProto аккаунт"""
    
    # Проверяем доступность Pyrogram при создании аккаунта
    # (чтобы сразу предупредить пользователя, а не только при авторизации)
    if not PYROGRAM_AVAILABLE:
        logger.warning("Pyrogram не установлен, но пользователь пытается создать MTProto аккаунт")
        raise HTTPException(
            status_code=503,
            detail="Функция MTProto временно недоступна. Обратитесь в поддержку."
        )
    
    # Проверяем что phone в правильном формате
    if not data.phone.startswith('+'):
        raise HTTPException(
            status_code=400,
            detail="Номер телефона должен быть в международном формате с + (например, +79991234567)"
        )
    
    # Если это default, снимаем default с других аккаунтов
    if data.is_default:
        db.query(TelegramMtprotoAccount).filter(
            TelegramMtprotoAccount.tenant_id == current_user.tenant_id
        ).update({"is_default": False})
    
    # Шифруем API hash
    api_hash_enc = encrypt_token(data.api_hash)
    
    # Создаем аккаунт
    account = TelegramMtprotoAccount(
        tenant_id=current_user.tenant_id,
        name=data.name,
        phone=data.phone,
        api_id=data.api_id,
        api_hash_enc=api_hash_enc,
        is_default=data.is_default,
        status="pending_auth"  # Требуется авторизация
    )
    
    db.add(account)
    db.commit()
    db.refresh(account)
    
    return account


@router.get("/mtproto/accounts", response_model=list[MtprotoAccountOut])
async def list_mtproto_accounts(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Получить список MTProto аккаунтов тенанта"""
    
    accounts = db.query(TelegramMtprotoAccount).filter(
        TelegramMtprotoAccount.tenant_id == current_user.tenant_id
    ).all()
    
    return accounts


@router.get("/mtproto/accounts/{account_id}", response_model=MtprotoAccountOut)
async def get_mtproto_account(
    account_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Получить информацию о MTProto аккаунте"""
    
    account = db.query(TelegramMtprotoAccount).filter(
        TelegramMtprotoAccount.id == account_id,
        TelegramMtprotoAccount.tenant_id == current_user.tenant_id
    ).first()
    
    if not account:
        raise HTTPException(status_code=404, detail="MTProto аккаунт не найден")
    
    return account


@router.put("/mtproto/accounts/{account_id}", response_model=MtprotoAccountOut)
async def update_mtproto_account(
    account_id: int,
    data: MtprotoAccountUpdate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Обновить MTProto аккаунт"""
    
    account = db.query(TelegramMtprotoAccount).filter(
        TelegramMtprotoAccount.id == account_id,
        TelegramMtprotoAccount.tenant_id == current_user.tenant_id
    ).first()
    
    if not account:
        raise HTTPException(status_code=404, detail="MTProto аккаунт не найден")
    
    # Обновляем поля
    if data.name is not None:
        account.name = data.name
    
    if data.is_default is not None:
        # Если делаем default, снимаем default с других
        if data.is_default:
            db.query(TelegramMtprotoAccount).filter(
                and_(
                    TelegramMtprotoAccount.tenant_id == current_user.tenant_id,
                    TelegramMtprotoAccount.id != account_id
                )
            ).update({"is_default": False})
        account.is_default = data.is_default
    
    if data.status is not None:
        account.status = data.status
    
    account.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(account)
    
    return account


@router.post("/mtproto/accounts/{account_id}/auth")
async def authenticate_mtproto_account(
    account_id: int,
    data: AuthCodeRequest | None = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    # Получаем код из body (если передан)
    # Если data пустое или code пустой/None - это запрос на отправку нового кода
    auth_code = data.code if data and data.code and data.code.strip() else None
    """
    Авторизовать MTProto аккаунт
    При первом вызове отправляется код в Telegram/SMS
    При втором вызове с code - завершается авторизация
    """
    from app.utils.encryption import decrypt_token
    import os
    from app.core.config import get_settings
    
    # Используем with_for_update для блокировки строки и предотвращения конкурентных запросов
    account = db.query(TelegramMtprotoAccount).filter(
        TelegramMtprotoAccount.id == account_id,
        TelegramMtprotoAccount.tenant_id == current_user.tenant_id
    ).with_for_update().first()
    
    if not account:
        raise HTTPException(status_code=404, detail="MTProto аккаунт не найден")
    
    try:
        # Расшифровываем API hash
        api_hash = decrypt_token(account.api_hash_enc)
        if not api_hash:
            raise HTTPException(status_code=500, detail="Не удалось расшифровать API hash")
        
        # Создаем путь для сессии
        settings = get_settings()
        session_base_path = os.path.join(os.getcwd(), settings.TELEGRAM_SESSION_PATH)
        os.makedirs(session_base_path, exist_ok=True)
        # Используем фиксированное имя для сессии, не связанное с session_path
        # session_path используется для временного хранения phone_code_hash
        # ВАЖНО: Client принимает только имя файла (без расширения) в параметре name
        session_name = f"mtproto_{account_id}"
        
        # Импортируем Pyrogram
        if not PYROGRAM_AVAILABLE:
            logger.error("Pyrogram не установлен. Установите: pip install pyrogram tgcrypto")
            raise HTTPException(
                status_code=503,
                detail="Сервис временно недоступен. Обратитесь в поддержку."
            )
        
        from pyrogram import Client
        
        # Создаем клиент
        # ВАЖНО: name - это имя файла сессии БЕЗ расширения и БЕЗ пути
        # workdir - директория где будет сохранен файл сессии
        # Pyrogram автоматически добавит .session к имени
        logger.info(f"[AUTH] Создание Pyrogram Client:")
        logger.info(f"[AUTH] - Телефон: {account.phone}")
        logger.info(f"[AUTH] - api_id: {account.api_id}")
        logger.info(f"[AUTH] - api_hash: {api_hash[:10]}... (первые 10 символов)")
        logger.info(f"[AUTH] - session_name: {session_name}")
        logger.info(f"[AUTH] - workdir: {session_base_path}")
        
        client = Client(
            name=session_name,
            api_id=account.api_id,
            api_hash=api_hash,
            phone_number=account.phone,
            workdir=session_base_path
        )
        logger.info(f"[AUTH] Client создан успешно для {account.phone}, session_name={session_name}")
        
        try:
            # Проверяем, есть ли уже сессия
            # Pyrogram сохраняет сессию в workdir с именем {name}.session
            session_file_path = os.path.join(session_base_path, f"{session_name}.session")
            session_exists = os.path.exists(session_file_path)
            
            if session_exists:
                # Сессия существует - пытаемся подключиться
                try:
                    await client.start()
                    me = await client.get_me()
                    account.status = "active"
                    account.username = me.username if me else None
                    account.updated_at = datetime.utcnow()
                    db.commit()
                    await client.stop()
                    
                    return {
                        "success": True,
                        "message": "Аккаунт успешно авторизован",
                        "username": me.username if me else None
                    }
                except Exception as start_error:
                    # Сессия невалидна - удаляем и начинаем заново
                    logger.warning(f"Сессия невалидна, начинаем авторизацию заново: {start_error}")
                    try:
                        os.remove(session_file_path)
                    except:
                        pass
            
            # Сессии нет или она невалидна - отправляем код
            if not auth_code:
                # Первый шаг: подключаемся и отправляем код
                logger.info(f"[AUTH] ===== ЗАПРОС КОДА ДЛЯ АККАУНТА {account_id} (телефон: {account.phone}) в {datetime.utcnow().isoformat()} =====")
                logger.info(f"[AUTH] Текущий session_path: {account.session_path[:100] if account.session_path else 'None'}...")
                
                # ВАЖНО: Сразу после получения блокировки with_for_update() проверяем флаг "processing"
                # Это предотвращает параллельные запросы - второй запрос увидит флаг и отклонится
                processing_flag = "processing_auth_request"
                if account.session_path == processing_flag:
                    logger.warning(f"[AUTH] ===== БЛОКИРОВКА ДУБЛИКАТА: Аккаунт {account_id} уже обрабатывается другим запросом - session_path == processing_flag =====")
                    db.rollback()
                    raise HTTPException(
                        status_code=429,
                        detail="Запрос на авторизацию уже обрабатывается. Подождите немного."
                    )
                
                # КРИТИЧЕСКАЯ ПРОВЕРКА: проверяем, не запрашивался ли код недавно (менее 2 минут)
                # Это предотвращает множественные запросы кода в короткий период
                if account.session_path and account.session_path.startswith("temp_auth_"):
                    try:
                        encoded_data = account.session_path.replace("temp_auth_", "")
                        json_str = base64.b64decode(encoded_data.encode('utf-8')).decode('utf-8')
                        temp_auth_data = json.loads(json_str)
                        created_at = temp_auth_data.get("created_at", 0)
                        time_passed = datetime.utcnow().timestamp() - created_at
                        # УВЕЛИЧИВАЕМ защиту: если код был запрошен меньше 2 минут назад - не отправляем новый
                        # Это предотвращает ситуацию, когда пользователь несколько раз нажимает кнопку
                        if time_passed < 120:  # 2 минуты вместо 30 секунд
                            logger.warning(f"[AUTH] БЛОКИРОВКА ДУБЛИКАТА: Попытка запросить код повторно слишком быстро для аккаунта {account_id} (прошло {time_passed:.1f} секунд, требуется минимум 120 секунд)")
                            db.rollback()
                            raise HTTPException(
                                status_code=429,
                                detail=f"Код был запрошен недавно (прошло {int(time_passed)} секунд). Подождите {int(120 - time_passed)} секунд перед повторным запросом."
                            )
                        # Если прошло больше 2 минут, очищаем старые данные и разрешаем новый запрос
                        logger.info(f"[AUTH] Предыдущий код был запрошен {time_passed:.1f} секунд назад ({time_passed/60:.1f} минут), разрешаем новый запрос")
                    except HTTPException:
                        raise
                    except Exception as decode_err:
                        # Если не удалось декодировать - очищаем и продолжаем отправку
                        logger.warning(f"[AUTH] Не удалось декодировать temp_auth_data для аккаунта {account_id}, очищаем: {decode_err}")
                
                # КРИТИЧЕСКИ ВАЖНО: Устанавливаем флаг "processing" в ТОЙ ЖЕ транзакции с блокировкой
                # НЕ делаем commit здесь! Это гарантирует что второй запрос будет ждать блокировки
                # и увидит результат только после того, как мы завершим отправку кода
                logger.info(f"[AUTH] Устанавливаем флаг processing для аккаунта {account_id} в транзакции с блокировкой (БЛОКИРОВКА ДУБЛИКАТОВ)")
                account.session_path = processing_flag
                db.flush()  # Flush - изменения видны в текущей транзакции, но транзакция НЕ закрывается
                
                # ВАЖНО: Блокировка with_for_update() остается активной до конца транзакции (до commit)
                # Второй запрос, который попытается получить блокировку на строке 210, будет ЖДАТЬ
                # Только после commit (строка 427) блокировка снимется и второй запрос сможет продолжить
                logger.info(f"[AUTH] Флаг processing установлен, блокировка with_for_update() активна. Второй запрос будет ждать блокировки. Аккаунт {account_id}")
                
                try:
                    # Отправляем код
                    # ВАЖНО: нужно подключиться перед send_code()
                    # При каждом новом send_code Telegram генерирует новый phone_code_hash
                    # Старый phone_code_hash становится невалидным
                    logger.info(f"[AUTH] Подключение к Telegram API для {account.phone} (аккаунт {account_id})")
                    logger.info(f"[AUTH] - api_id: {account.api_id}")
                    logger.info(f"[AUTH] - api_hash: {api_hash[:10]}... (первые 10 символов)")
                    logger.info(f"[AUTH] - phone: {account.phone}")
                    await client.connect()
                    logger.info(f"[AUTH] Подключение к Telegram API выполнено успешно")
                    
                    logger.info(f"[AUTH] ===== ВЫЗОВ send_code =====")
                    logger.info(f"[AUTH] Телефон: {account.phone}, Аккаунт ID: {account_id}")
                    logger.info(f"[AUTH] api_id: {account.api_id}")
                    logger.info(f"[AUTH] БЛОКИРОВКА with_for_update() АКТИВНА - второй запрос будет ждать")
                    
                    # ВАЖНО: Проверяем, был ли старый phone_code_hash (он станет невалидным после send_code)
                    old_session_path = account.session_path
                    if old_session_path and old_session_path.startswith("temp_auth_"):
                        logger.warning(f"[AUTH] ПЕРЕЗАПИСЬ: Старый phone_code_hash будет перезаписан для аккаунта {account_id} - предыдущий код стал невалидным")
                        try:
                            old_encoded = old_session_path.replace("temp_auth_", "")
                            old_json = base64.b64decode(old_encoded.encode('utf-8')).decode('utf-8')
                            old_data = json.loads(old_json)
                            old_hash = old_data.get("phone_code_hash", "")[:20] if old_data.get("phone_code_hash") else "None"
                            logger.warning(f"[AUTH] Старый phone_code_hash (первые 20): {old_hash}... - будет невалиден после нового send_code")
                        except:
                            pass
                    
                    # ВАЖНО: send_code() может вернуть успешно, но код может не прийти
                    # Это может произойти если номер неверный, rate limit, или другие проблемы
                    def _mask_phone(p: str) -> str:
                        if not p:
                            return "unknown"
                        digits = ''.join(ch for ch in p if ch.isdigit())
                        if len(digits) <= 4:
                            return "***"
                        return f"{digits[:-4]}****"

                    logger.info(f"[AUTH] Вызов client.send_code() для { _mask_phone(account.phone) } (аккаунт {account_id})")
                    try:
                        sent_code = await client.send_code(account.phone)
                        logger.info(f"[AUTH] send_code() вернул результат: type={type(sent_code)}")
                        
                        # Проверяем результат
                        if not sent_code:
                            logger.error(f"[AUTH] send_code() вернул None для {account.phone} (аккаунт {account_id})")
                            raise Exception("send_code() вернул None")
                        
                        # Логируем все атрибуты объекта sent_code для диагностики
                        logger.info(f"[AUTH] Атрибуты sent_code: {dir(sent_code)}")
                        try:
                            logger.info(f"[AUTH] sent_code.__dict__: {getattr(sent_code, '__dict__', 'N/A')}")
                        except:
                            pass
                        
                        new_phone_code_hash = sent_code.phone_code_hash
                        if not new_phone_code_hash:
                            logger.error(f"[AUTH] send_code() вернул результат без phone_code_hash для {account.phone} (аккаунт {account_id})")
                            raise Exception("send_code() вернул результат без phone_code_hash")
                        
                        # Проверяем тип кода (SMS, Telegram app и т.д.)
                        code_type = getattr(sent_code, 'type', None)
                        next_type = getattr(sent_code, 'next_type', None)
                        timeout = getattr(sent_code, 'timeout', None)
                        
                        logger.info(f"[AUTH] Тип кода: {code_type}")
                        logger.info(f"[AUTH] Следующий тип (next_type): {next_type}")
                        logger.info(f"[AUTH] Timeout: {timeout}")
                        
                        created_timestamp = datetime.utcnow().timestamp()
                        created_iso = datetime.utcnow().isoformat()
                        
                        # Логируем полный hash для диагностики
                        logger.info(f"[AUTH] ===== КОД ОТПРАВЛЕН В TELEGRAM =====")
                        logger.info(f"[AUTH] Телефон: { _mask_phone(account.phone) }, Аккаунт ID: {account_id}")
                        logger.info(f"[AUTH] Время отправки: {created_iso}")
                        logger.info(f"[AUTH] Тип отправки кода: {code_type}, next_type: {next_type}")
                        logger.info(f"[AUTH] phone_code_hash (первые 40 символов): {new_phone_code_hash[:40] if new_phone_code_hash else 'None'}")
                        logger.info(f"[AUTH] phone_code_hash (полный): {new_phone_code_hash}")
                        logger.warning(f"[AUTH] ⚠️ ВАЖНО: Код должен прийти В ПРИЛОЖЕНИЕ TELEGRAM (не SMS!) на номер { _mask_phone(account.phone) }")
                        logger.warning(f"[AUTH] ⚠️ Если код не приходит, проверьте: 1) Открыто ли приложение Telegram на устройстве с номером { _mask_phone(account.phone) }, 2) Правильность номера телефона, 3) Правильность api_id/api_hash")
                        
                    except Exception as send_code_error:
                        logger.error(f"[AUTH] Ошибка при вызове send_code() для { _mask_phone(account.phone) } (аккаунт {account_id}): {send_code_error}", exc_info=True)
                        raise
                    
                    # ВАЖНО: Сохраняем НОВЫЙ phone_code_hash и делаем commit
                    # Старый phone_code_hash автоматически становится невалидным после вызова send_code()
                    # Каждый вызов send_code() генерирует новый phone_code_hash и делает старый невалидным
                    temp_auth_data = {
                        "phone_code_hash": new_phone_code_hash,
                        "created_at": created_timestamp,
                        "expires_at": created_timestamp + 900  # 15 минут для phone_code_hash
                    }
                    # Кодируем в base64 для безопасного хранения в строке
                    json_str = json.dumps(temp_auth_data)
                    encoded_data = base64.b64encode(json_str.encode('utf-8')).decode('utf-8')
                    account.session_path = f"temp_auth_{encoded_data}"
                    
                    # КРИТИЧЕСКИ ВАЖНО: Commit ТОЛЬКО после успешной отправки кода
                    # До этого момента блокировка with_for_update() активна и второй запрос ждет
                    # После commit блокировка снимается, но код уже отправлен
                    db.commit()
                    logger.info(f"[AUTH] phone_code_hash сохранен в БД, timestamp: {created_timestamp}")
                    logger.info(f"[AUTH] Commit выполнен, блокировка снята")
                    
                    # Закрываем клиент (send_code может оставить соединение открытым)
                    try:
                        await client.disconnect()
                    except:
                        pass
                    
                    return {
                        "success": False,
                        "message": f"Код авторизации отправлен в Telegram на номер {account.phone}. Проверьте приложение Telegram (не SMS) и введите код в модальном окне.",
                        "requires_code": True
                    }
                except Exception as send_error:
                    # При ошибке отправки очищаем session_path (включая флаг processing), чтобы можно было повторить попытку
                    logger.error(f"[AUTH] Ошибка отправки кода для аккаунта {account_id}: {send_error}")
                    account.session_path = None
                    db.rollback()  # Откатываем транзакцию, блокировка снимается
                    logger.info(f"[AUTH] Транзакция откачена из-за ошибки, блокировка снята для аккаунта {account_id}")
                    try:
                        await client.disconnect()
                    except:
                        pass
                    
                    error_str = str(send_error)
                    logger.error(f"Ошибка отправки кода для {account.phone}: {send_error}", exc_info=True)
                    
                    # Обработка FLOOD_WAIT - Telegram заблокировал запросы из-за частых попыток
                    if "FLOOD_WAIT" in error_str.upper() or "flood" in error_str.lower():
                        # Извлекаем время ожидания из ошибки (если есть)
                        import re
                        wait_match = re.search(r'(\d+)', error_str)
                        wait_seconds = int(wait_match.group(1)) if wait_match else 0
                        wait_minutes = wait_seconds // 60
                        wait_hours = wait_minutes // 60
                        
                        # Формируем понятное сообщение о времени ожидания
                        if wait_hours > 0:
                            if wait_minutes % 60 > 0:
                                wait_time = f"{wait_hours} ч. {wait_minutes % 60} мин."
                            else:
                                wait_time = f"{wait_hours} ч."
                        elif wait_minutes > 0:
                            wait_time = f"{wait_minutes} мин."
                        else:
                            wait_time = f"{wait_seconds} сек."
                        
                        wait_msg = f"Telegram временно заблокировал отправку кодов из-за частых запросов. Подождите {wait_time} и попробуйте снова."
                        
                        raise HTTPException(
                            status_code=429,
                            detail=wait_msg
                        )
                    
                    raise HTTPException(
                        status_code=400,
                        detail=f"Ошибка отправки кода: {str(send_error)}"
                    )
            else:
                # Второй шаг: вводим код
                try:
                    # Получаем phone_code_hash из временного хранилища
                    # ВАЖНО: phone_code_hash должен соответствовать коду, который пользователь получил
                    # Если пользователь запросил новый код, нужно использовать phone_code_hash от нового запроса
                    phone_code_hash = None
                    if account.session_path and account.session_path.startswith("temp_auth_"):
                        try:
                            encoded_data = account.session_path.replace("temp_auth_", "")
                            json_str = base64.b64decode(encoded_data.encode('utf-8')).decode('utf-8')
                            temp_auth_data = json.loads(json_str)
                            phone_code_hash = temp_auth_data.get("phone_code_hash")
                            created_at = temp_auth_data.get("created_at", 0)
                            expires_at = temp_auth_data.get("expires_at", created_at + 900)  # По умолчанию 15 минут
                            current_time = datetime.utcnow().timestamp()
                            
                            # Логируем время создания для диагностики
                            time_passed = current_time - created_at
                            time_until_expiry = expires_at - current_time
                            created_iso = datetime.utcfromtimestamp(created_at).isoformat() if created_at > 0 else "неизвестно"
                            current_iso = datetime.utcnow().isoformat()
                            logger.info(f"[AUTH] ===== ПОДТВЕРЖДЕНИЕ КОДА =====")
                            logger.info(f"[AUTH] Телефон: {account.phone}, Аккаунт ID: {account_id}")
                            logger.info(f"[AUTH] Текущее время: {current_iso}")
                            logger.info(f"[AUTH] phone_code_hash создан: {created_iso} (timestamp: {created_at})")
                            logger.info(f"[AUTH] Прошло времени: {time_passed:.1f} секунд ({time_passed/60:.2f} минут)")
                            logger.info(f"[AUTH] Осталось до истечения: {time_until_expiry:.1f} секунд")
                            logger.info(f"[AUTH] phone_code_hash (первые 40 символов): {phone_code_hash[:40] if phone_code_hash else 'None'}")
                            logger.info(f"[AUTH] phone_code_hash (полный): {phone_code_hash}")
                            
                            if not phone_code_hash:
                                logger.warning(f"[AUTH] phone_code_hash не найден в temp_auth_data для аккаунта {account_id}")
                                raise HTTPException(
                                    status_code=400,
                                    detail="Сессия авторизации повреждена. Нажмите 'Авторизовать' снова."
                                )
                            
                            # ВАЖНО: Проверяем срок действия phone_code_hash
                            # Код может истечь, если прошло больше 15 минут или если был запрошен новый код
                            if current_time > expires_at:
                                logger.warning(f"[AUTH] phone_code_hash истек для аккаунта {account_id}: создан {time_passed:.1f} секунд назад, срок действия истек {abs(time_until_expiry):.1f} секунд назад")
                                # Очищаем истекший phone_code_hash
                                account.session_path = None
                                db.commit()
                                raise HTTPException(
                                    status_code=400,
                                    detail="Код авторизации истек. Нажмите 'Авторизовать' для получения нового кода."
                                )
                            
                            # Дополнительная проверка: если код был создан больше 15 минут назад, он истек
                            # (даже если expires_at не установлен)
                            if time_passed > 900:  # 15 минут
                                logger.warning(f"[AUTH] phone_code_hash слишком старый для аккаунта {account_id}: {time_passed:.1f} секунд ({time_passed/60:.1f} минут)")
                                account.session_path = None
                                db.commit()
                                raise HTTPException(
                                    status_code=400,
                                    detail="Код авторизации истек. Нажмите 'Авторизовать' для получения нового кода."
                                )
                        except HTTPException:
                            raise
                        except Exception as decode_error:
                            logger.error(f"Ошибка декодирования temp_auth_data: {decode_error}", exc_info=True)
                            raise HTTPException(
                                status_code=400,
                                detail="Сессия авторизации повреждена. Нажмите 'Авторизовать' снова."
                            )
                    else:
                        raise HTTPException(
                            status_code=400,
                            detail="Сессия авторизации не найдена. Нажмите 'Авторизовать' снова для получения нового кода."
                        )
                    
                    if not phone_code_hash:
                        raise HTTPException(
                            status_code=400,
                            detail="Сессия авторизации не найдена. Нажмите 'Авторизовать' снова для получения нового кода."
                        )
                    
                    await client.connect()
                    
                    # Пытаемся войти с кодом
                    # ВАЖНО: код должен соответствовать phone_code_hash
                    # Если пользователь ввел код от предыдущего запроса, а phone_code_hash уже новый - будет ошибка PHONE_CODE_EXPIRED
                    try:
                        # Используем строковый код, так как sign_in принимает строку
                        code_str = str(auth_code).strip()
                        logger.info(f"[AUTH] ===== ВЫЗОВ sign_in =====")
                        logger.info(f"[AUTH] Код (длина: {len(code_str)}, первые 2 цифры: {code_str[:2] if len(code_str) >= 2 else code_str})")
                        logger.info(f"[AUTH] phone_code_hash (первые 40 символов): {phone_code_hash[:40] if phone_code_hash else 'None'}")
                        logger.info(f"[AUTH] phone_code_hash (полный): {phone_code_hash}")
                        logger.info(f"[AUTH] phone_code_hash создан {time_passed:.1f} секунд назад ({time_passed/60:.2f} минут)")
                        signed_in = await client.sign_in(account.phone, phone_code_hash, code_str)
                        logger.info(f"[AUTH] sign_in успешно выполнен")
                    except Exception as sign_error:
                        error_str = str(sign_error)
                        error_str_lower = error_str.lower()
                        logger.error(f"[AUTH] ===== ОШИБКА sign_in =====")
                        logger.error(f"[AUTH] Ошибка: {error_str}")
                        logger.error(f"[AUTH] Код: {code_str[:2] if len(code_str) >= 2 else code_str}... (длина: {len(code_str)})")
                        logger.error(f"[AUTH] phone_code_hash (первые 40 символов): {phone_code_hash[:40] if phone_code_hash else 'None'}")
                        logger.error(f"[AUTH] phone_code_hash (полный): {phone_code_hash}")
                        logger.error(f"[AUTH] phone_code_hash создан {time_passed:.1f} секунд назад ({time_passed/60:.2f} минут)")
                        try:
                            await client.disconnect()
                        except:
                            pass
                        if "password" in error_str_lower or "2fa" in error_str_lower:
                            # Очищаем временное хранилище
                            account.session_path = None
                            db.commit()
                            return {
                                "success": False,
                                "message": "Требуется пароль двухфакторной аутентификации (2FA). Введите пароль от аккаунта Telegram.",
                                "requires_password": True
                            }
                        elif "phone_code_expired" in error_str_lower or "expired" in error_str_lower:
                            # Код истек - очищаем временное хранилище
                            logger.warning(f"[AUTH] Код истек (PHONE_CODE_EXPIRED). Прошло {time_passed:.1f} секунд ({time_passed/60:.2f} минут) с момента создания phone_code_hash")
                            account.session_path = None
                            db.commit()
                            raise HTTPException(
                                status_code=400,
                                detail="Код авторизации истек. Это может произойти если: 1) прошло слишком много времени с момента получения кода, 2) был запрошен новый код. Нажмите 'Авторизовать' для получения нового кода."
                            )
                        else:
                            # Другая ошибка - очищаем временное хранилище
                            account.session_path = None
                            db.commit()
                            raise
                    
                    # Успешно авторизованы
                    me = await client.get_me()
                    account.status = "active"
                    account.username = me.username if me else None
                    account.session_path = None  # Очищаем временное хранилище
                    account.updated_at = datetime.utcnow()
                    db.commit()
                    
                    # Сохраняем сессию
                    await client.disconnect()
                    # Сессия уже сохранена Pyrogram в файл
                    
                    return {
                        "success": True,
                        "message": "Аккаунт успешно авторизован",
                        "username": me.username if me else None
                    }
                except HTTPException:
                    raise
                except Exception as sign_in_error:
                    try:
                        await client.disconnect()
                    except:
                        pass
                    # Очищаем временное хранилище при ошибке
                    account.session_path = None
                    db.commit()
                    raise HTTPException(
                        status_code=400,
                        detail=f"Неверный код авторизации: {str(sign_in_error)}"
                    )
                        
        except HTTPException:
            raise
        except Exception as e:
            try:
                await client.disconnect()
            except:
                pass
            
            logger.error(f"Ошибка авторизации MTProto аккаунта {account_id}: {e}", exc_info=True)
            raise HTTPException(
                status_code=400,
                detail=f"Ошибка авторизации: {str(e)}"
            )
                
    except HTTPException:
        raise
    except Exception as e:
        account.status = "error"
        account.updated_at = datetime.utcnow()
        db.commit()
        
        error_msg = str(e)
        logger.error(f"Ошибка авторизации MTProto аккаунта {account_id}: {error_msg}", exc_info=True)
        
        raise HTTPException(
            status_code=400,
            detail=f"Ошибка авторизации: {error_msg}"
        )


@router.delete("/mtproto/accounts/{account_id}")
async def delete_mtproto_account(
    account_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Удалить MTProto аккаунт"""
    
    account = db.query(TelegramMtprotoAccount).filter(
        TelegramMtprotoAccount.id == account_id,
        TelegramMtprotoAccount.tenant_id == current_user.tenant_id
    ).first()
    
    if not account:
        raise HTTPException(status_code=404, detail="MTProto аккаунт не найден")
    
    # Закрываем клиент если он открыт
    await close_telegram_client(account_id=account_id)
    
    # Удаляем файл сессии если есть
    if account.session_path:
        import os
        from app.core.config import get_settings
        settings = get_settings()
        session_file = os.path.join(settings.TELEGRAM_SESSION_PATH, account.session_path + ".session")
        if os.path.exists(session_file):
            try:
                os.remove(session_file)
            except:
                pass
    
    db.delete(account)
    db.commit()
    
    return {"success": True, "message": "MTProto аккаунт удален"}
