"""Утилиты для синхронизации токена внешней админки."""

from __future__ import annotations

import structlog
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError

from app.config import settings
from app.database.database import AsyncSessionLocal
from app.database.models import SystemSetting
from app.services.system_settings_service import (
    ReadOnlySettingError,
    bot_configuration_service,
)


logger = structlog.get_logger(__name__)


async def ensure_external_admin_token(
    bot_username: str | None,
    bot_id: int | None,
) -> str | None:
    """Генерирует и сохраняет токен внешней админки, если требуется."""

    username_raw = (bot_username or '').strip()
    if not username_raw:
        logger.warning(
            '⚠️ Не удалось обеспечить токен внешней админки: username бота отсутствует',
        )
        return None

    normalized_username = username_raw.lstrip('@').lower()
    if not normalized_username:
        logger.warning(
            '⚠️ Не удалось обеспечить токен внешней админки: username пустой после нормализации',
        )
        return None

    try:
        token = settings.build_external_admin_token(normalized_username)
    except Exception as error:  # pragma: no cover - защитный блок
        logger.error('❌ Ошибка генерации токена внешней админки', error=error)
        return None

    try:
        async with AsyncSessionLocal() as session:
            result = await session.execute(
                select(SystemSetting.key, SystemSetting.value).where(
                    SystemSetting.key.in_(['EXTERNAL_ADMIN_TOKEN', 'EXTERNAL_ADMIN_TOKEN_BOT_ID'])
                )
            )
            rows = dict(result.all())
            existing_token = rows.get('EXTERNAL_ADMIN_TOKEN')
            existing_bot_id_raw = rows.get('EXTERNAL_ADMIN_TOKEN_BOT_ID')

            existing_bot_id: int | None = None
            if existing_bot_id_raw is not None:
                try:
                    existing_bot_id = int(existing_bot_id_raw)
                except (TypeError, ValueError):  # pragma: no cover - защита от мусорных значений
                    logger.warning(
                        '⚠️ Не удалось разобрать сохраненный идентификатор бота внешней админки',
                        existing_bot_id_raw=existing_bot_id_raw,
                    )

            if existing_token == token and existing_bot_id == bot_id:
                if settings.get_external_admin_token() != token:
                    settings.EXTERNAL_ADMIN_TOKEN = token
                if existing_bot_id != settings.EXTERNAL_ADMIN_TOKEN_BOT_ID:
                    settings.EXTERNAL_ADMIN_TOKEN_BOT_ID = existing_bot_id
                return token

            if existing_bot_id is not None and bot_id is not None and existing_bot_id != bot_id:
                logger.error(
                    '❌ Обнаружено несовпадение ID бота для токена внешней админки: сохранен , текущий',
                    existing_bot_id=existing_bot_id,
                    bot_id=bot_id,
                )

                try:
                    await bot_configuration_service.reset_value(
                        session,
                        'EXTERNAL_ADMIN_TOKEN',
                        force=True,
                    )
                    await bot_configuration_service.reset_value(
                        session,
                        'EXTERNAL_ADMIN_TOKEN_BOT_ID',
                        force=True,
                    )
                    await session.commit()
                    logger.warning(
                        '⚠️ Токен внешней админки очищен из-за несовпадения идентификаторов бота',
                    )
                except Exception as cleanup_error:  # pragma: no cover - защитный блок
                    await session.rollback()
                    logger.error(
                        '❌ Не удалось очистить токен внешней админки после обнаружения подмены',
                        cleanup_error=cleanup_error,
                    )
                finally:
                    settings.EXTERNAL_ADMIN_TOKEN = None
                    settings.EXTERNAL_ADMIN_TOKEN_BOT_ID = None

                return None

            updates: list[tuple[str, object]] = []
            if existing_token != token:
                updates.append(('EXTERNAL_ADMIN_TOKEN', token))

            if bot_id is not None and existing_bot_id != bot_id:
                updates.append(('EXTERNAL_ADMIN_TOKEN_BOT_ID', bot_id))

            if not updates:
                # Токен совпал, но могли отсутствовать значения в настройках приложения
                if settings.get_external_admin_token() != (existing_token or token):
                    settings.EXTERNAL_ADMIN_TOKEN = existing_token or token
                if existing_bot_id is not None and (existing_bot_id != settings.EXTERNAL_ADMIN_TOKEN_BOT_ID):
                    settings.EXTERNAL_ADMIN_TOKEN_BOT_ID = existing_bot_id
                elif bot_id is not None and bot_id != settings.EXTERNAL_ADMIN_TOKEN_BOT_ID and existing_bot_id is None:
                    settings.EXTERNAL_ADMIN_TOKEN_BOT_ID = bot_id
                return existing_token or token

            try:
                for key, value in updates:
                    await bot_configuration_service.set_value(
                        session,
                        key,
                        value,
                        force=True,
                    )
                await session.commit()
                logger.info('✅ Токен внешней админки синхронизирован для @', normalized_username=normalized_username)
            except ReadOnlySettingError:  # pragma: no cover - force=True предотвращает исключение
                await session.rollback()
                logger.warning(
                    '⚠️ Не удалось сохранить токен внешней админки из-за ограничения доступа',
                )
                return None

            return token
    except SQLAlchemyError as error:
        logger.error('❌ Ошибка сохранения токена внешней админки', error=error)
        return None
