import structlog
from aiogram import Dispatcher, F, types
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from sqlalchemy.ext.asyncio import AsyncSession

from app.database.models import User
from app.services.version_service import version_service
from app.utils.decorators import admin_required, error_handler


logger = structlog.get_logger(__name__)


def get_updates_keyboard(language: str = 'ru') -> InlineKeyboardMarkup:
    buttons = [
        [InlineKeyboardButton(text='🔄 Проверить обновления', callback_data='admin_updates_check')],
        [InlineKeyboardButton(text='📋 Информация о версии', callback_data='admin_updates_info')],
        [
            InlineKeyboardButton(
                text='🔗 Открыть репозиторий', url=f'https://github.com/{version_service.repo}/releases'
            )
        ],
        [InlineKeyboardButton(text='◀️ Назад', callback_data='admin_panel')],
    ]

    return InlineKeyboardMarkup(inline_keyboard=buttons)


def get_version_info_keyboard(language: str = 'ru') -> InlineKeyboardMarkup:
    buttons = [
        [InlineKeyboardButton(text='🔄 Обновить', callback_data='admin_updates_info')],
        [InlineKeyboardButton(text='◀️ К обновлениям', callback_data='admin_updates')],
    ]

    return InlineKeyboardMarkup(inline_keyboard=buttons)


@admin_required
@error_handler
async def show_updates_menu(callback: types.CallbackQuery, db_user: User, db: AsyncSession):
    try:
        version_info = await version_service.get_version_info()

        current_version = version_info['current_version']
        has_updates = version_info['has_updates']
        total_newer = version_info['total_newer']
        last_check = version_info['last_check']

        status_icon = '🆕' if has_updates else '✅'
        status_text = f'Доступно {total_newer} обновлений' if has_updates else 'Актуальная версия'

        last_check_text = ''
        if last_check:
            last_check_text = f'\n🕐 Последняя проверка: {last_check.strftime("%d.%m.%Y %H:%M")}'

        message = f"""🔄 <b>СИСТЕМА ОБНОВЛЕНИЙ</b>

📦 <b>Текущая версия:</b> <code>{current_version}</code>
{status_icon} <b>Статус:</b> {status_text}

🔗 <b>Репозиторий:</b> {version_service.repo}{last_check_text}

ℹ️ Система автоматически проверяет обновления каждый час и отправляет уведомления о новых версиях."""

        await callback.message.edit_text(
            message, reply_markup=get_updates_keyboard(db_user.language), parse_mode='HTML'
        )
        await callback.answer()

    except Exception as e:
        if 'message is not modified' in str(e).lower():
            logger.debug('📝 Сообщение не изменено в show_updates_menu')
            await callback.answer()
            return
        logger.error('Ошибка показа меню обновлений', error=e)
        await callback.answer('❌ Ошибка загрузки меню обновлений', show_alert=True)


@admin_required
@error_handler
async def check_updates(callback: types.CallbackQuery, db_user: User, db: AsyncSession):
    await callback.answer('🔄 Проверяю обновления...')

    try:
        has_updates, newer_releases = await version_service.check_for_updates(force=True)

        if not has_updates:
            message = f"""✅ <b>ОБНОВЛЕНИЯ НЕ НАЙДЕНЫ</b>

📦 <b>Текущая версия:</b> <code>{version_service.current_version}</code>
🎯 <b>Статус:</b> У вас установлена последняя версия

🔗 <b>Репозиторий:</b> {version_service.repo}"""

        else:
            updates_list = []
            for i, release in enumerate(newer_releases[:5]):
                icon = version_service.format_version_display(release).split()[0]
                updates_list.append(f'{i + 1}. {icon} <code>{release.tag_name}</code> • {release.formatted_date}')

            updates_text = '\n'.join(updates_list)
            more_text = f'\n\n📋 И еще {len(newer_releases) - 5} обновлений...' if len(newer_releases) > 5 else ''

            message = f"""🆕 <b>НАЙДЕНЫ ОБНОВЛЕНИЯ</b>

📦 <b>Текущая версия:</b> <code>{version_service.current_version}</code>
🎯 <b>Доступно обновлений:</b> {len(newer_releases)}

📋 <b>Последние версии:</b>
{updates_text}{more_text}

🔗 <b>Репозиторий:</b> {version_service.repo}"""

        keyboard = get_updates_keyboard(db_user.language)

        if has_updates:
            keyboard.inline_keyboard.insert(
                -2, [InlineKeyboardButton(text='📋 Подробнее о версиях', callback_data='admin_updates_info')]
            )

        await callback.message.edit_text(message, reply_markup=keyboard, parse_mode='HTML')

    except Exception as e:
        if 'message is not modified' in str(e).lower():
            logger.debug('📝 Сообщение не изменено в check_updates')
            return
        logger.error('Ошибка проверки обновлений', error=e)
        await callback.message.edit_text(
            f'❌ <b>ОШИБКА ПРОВЕРКИ ОБНОВЛЕНИЙ</b>\n\n'
            f'Не удалось связаться с сервером GitHub.\n'
            f'Попробуйте позже.\n\n'
            f'📦 <b>Текущая версия:</b> <code>{version_service.current_version}</code>',
            reply_markup=get_updates_keyboard(db_user.language),
            parse_mode='HTML',
        )


@admin_required
@error_handler
async def show_version_info(callback: types.CallbackQuery, db_user: User, db: AsyncSession):
    await callback.answer('📋 Загружаю информацию о версиях...')

    try:
        version_info = await version_service.get_version_info()

        current_version = version_info['current_version']
        current_release = version_info['current_release']
        newer_releases = version_info['newer_releases']
        has_updates = version_info['has_updates']
        last_check = version_info['last_check']

        current_info = '📦 <b>ТЕКУЩАЯ ВЕРСИЯ</b>\n\n'

        if current_release:
            current_info += f'🏷️ <b>Версия:</b> <code>{current_release.tag_name}</code>\n'
            current_info += f'📅 <b>Дата релиза:</b> {current_release.formatted_date}\n'
            if current_release.short_description:
                current_info += f'📝 <b>Описание:</b>\n{current_release.short_description}\n'
        else:
            current_info += f'🏷️ <b>Версия:</b> <code>{current_version}</code>\n'
            current_info += 'ℹ️ <b>Статус:</b> Информация о релизе недоступна\n'

        message_parts = [current_info]

        if has_updates and newer_releases:
            updates_info = '\n🆕 <b>ДОСТУПНЫЕ ОБНОВЛЕНИЯ</b>\n\n'

            for i, release in enumerate(newer_releases):
                icon = '🔥' if i == 0 else '📦'
                if release.prerelease:
                    icon = '🧪'
                elif release.is_dev:
                    icon = '🔧'

                updates_info += f'{icon} <b>{release.tag_name}</b>\n'
                updates_info += f'   📅 {release.formatted_date}\n'
                if release.short_description:
                    updates_info += f'   📝 {release.short_description}\n'
                updates_info += '\n'

            message_parts.append(updates_info.rstrip())

        system_info = '\n🔧 <b>СИСТЕМА ОБНОВЛЕНИЙ</b>\n\n'
        system_info += f'🔗 <b>Репозиторий:</b> {version_service.repo}\n'
        system_info += f'⚡ <b>Автопроверка:</b> {"Включена" if version_service.enabled else "Отключена"}\n'
        system_info += '🕐 <b>Интервал:</b> Каждый час\n'

        if last_check:
            system_info += f'🕐 <b>Последняя проверка:</b> {last_check.strftime("%d.%m.%Y %H:%M")}\n'

        message_parts.append(system_info.rstrip())

        final_message = '\n'.join(message_parts)

        if len(final_message) > 4000:
            final_message = final_message[:3900] + '\n\n... (информация обрезана)'

        await callback.message.edit_text(
            final_message,
            reply_markup=get_version_info_keyboard(db_user.language),
            parse_mode='HTML',
            disable_web_page_preview=True,
        )

    except Exception as e:
        if 'message is not modified' in str(e).lower():
            logger.debug('📝 Сообщение не изменено в show_version_info')
            return
        logger.error('Ошибка получения информации о версиях', error=e)
        await callback.message.edit_text(
            f'❌ <b>ОШИБКА ЗАГРУЗКИ</b>\n\n'
            f'Не удалось получить информацию о версиях.\n\n'
            f'📦 <b>Текущая версия:</b> <code>{version_service.current_version}</code>',
            reply_markup=get_version_info_keyboard(db_user.language),
            parse_mode='HTML',
        )


def register_handlers(dp: Dispatcher):
    dp.callback_query.register(show_updates_menu, F.data == 'admin_updates')

    dp.callback_query.register(check_updates, F.data == 'admin_updates_check')

    dp.callback_query.register(show_version_info, F.data == 'admin_updates_info')
