from aiogram import Router, F, Bot
from aiogram.exceptions import TelegramAPIError, TelegramRetryAfter
from aiogram.filters import Command, CommandObject
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import StatesGroup, State
from aiogram.types import Message, CallbackQuery
from aiogram.utils.i18n import gettext as _

from bot.core.bots import BotInfo
from bot.filters import IsOwner
from bot.handlers.commands.settings.settings_cmd import settings_keyboard
from bot.templates import msg
from bot.utils import format_retry_time, status_clear
from configs import COMMANDS
from middleware.loggers import logger

__all__ = ("router",)

# Название команды
CMD: str = "set_description".lower()

# Роутер для обработки команды /set_description
router: Router = Router(name=f"{CMD}_cmd_router")


class SetBotDescriptionForm(StatesGroup):
    """Состояния FSM для изменения короткого описания бота."""
    new_description: State = State()


async def handle_set_bot_description(
        description: str,
        message: Message | CallbackQuery,
        state: FSMContext,
        bot: Bot
) -> None:
    """
    Установка короткого описания (short description) бота с обработкой FSM и ошибок API.

    Args:
        description (str): Новый текст описания (до 120 символов).
        message (Message | CallbackQuery): Сообщение или callback-запрос.
        state (FSMContext): Контекст FSM.
        bot (Bot): Экземпляр бота.
    """
    # Проверка ограничения Telegram
    if len(description) > 120:
        await msg(
            update=message,
            text=_("❌ Короткое описание бота должно быть не более 120 символов. Текущая длина: {length}").format(
                length=len(description)
            ),
            markup=settings_keyboard(),
            state=state
        )
        return

    try:
        # Установка нового короткого описания
        await bot.set_my_short_description(short_description=description)

        # Сохраняем текущее значение в BotInfo
        BotInfo.short_description = description

        # Сбрасываем состояние FSM
        await state.clear()

        # Отправляем сообщение об успехе
        await msg(
            update=message,
            text=_("✅ Короткое описание бота успешно изменено на: <b>{description}</b>").format(
                description=description
            ),
            markup=settings_keyboard(),
            state=state
        )

        logger.info(f"Короткое описание бота изменено на: {description}")

    except TelegramRetryAfter as e:
        retry_text: str = format_retry_time(e.retry_after)
        logger.warning(f"Превышен лимит запросов при смене short description. Попробуйте через {retry_text}")
        await msg(
            update=message,
            text=_("⚠️ Слишком частая смена короткого описания!\nПопробуйте снова через: <b>{retry_text}</b>").format(
                retry_text=retry_text
            ),
            markup=settings_keyboard(),
            state=state
        )

    except TelegramAPIError as e:
        logger.error(f"Ошибка Telegram API при изменении короткого описания: {e}")
        await msg(
            update=message,
            text=_("❌ Ошибка Telegram API при изменении короткого описания: <pre>{error}</pre>").format(error=str(e)),
            markup=settings_keyboard(),
            state=state
        )

    except Exception as e:
        logger.error(f"Непредвиденная ошибка при изменении короткого описания: {e}")
        await msg(
            update=message,
            text=_("❌ Непредвиденная ошибка при изменении короткого описания: <pre>{error}</pre>").format(error=str(e)),
            markup=settings_keyboard(),
            state=state
        )


@router.callback_query(F.data.lower() == CMD, IsOwner())
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner())
async def settings_cmd(
        message: Message | CallbackQuery,
        state: FSMContext,
        bot: Bot,
        command: CommandObject | None = None
) -> None:
    """
    Обработчик команды /set_description для короткого описания.

    Поддерживает:
        1. Немедленное изменение через аргумент (/set_description TEXT).
        2. Callback-запрос.
        3. FSM-ввод.
    """
    current_description: str = BotInfo.description

    # Вариант 1: если пользователь передал аргумент к команде
    if command and command.args:
        description: str = command.args.strip()
        if len(description) > 120:
            await msg(
                update=message,
                text=_("❌ Короткое описание не должно превышать 120 символов. Текущая длина: {length}").format(
                    length=len(description)
                ),
                markup=settings_keyboard(),
            state=state
            )
            return

        await handle_set_bot_description(description, message, state, bot)
        return

    # Вариант 2: без аргумента → включаем FSM
    await status_clear(update=message, state=state)
    text: str = _(
        "📝 <b>Смена короткого описания бота</b>\n\n"
        "Текущее короткое описание: <i>{current}</i>\n\n"
        "Введите новое короткое описание (максимум 120 символов):"
    ).format(current=current_description)

    await msg(update=message, text=text, markup=settings_keyboard(), state=state)
    await state.set_state(SetBotDescriptionForm.new_description)


@router.message(SetBotDescriptionForm.new_description, IsOwner())
async def process_new_bot_description(
        message: Message,
        state: FSMContext,
        bot: Bot
) -> None:
    """
    Обработка ввода нового короткого описания через FSM.
    """
    description: str = message.text.strip()

    if not description:
        await message.answer(_("❌ Пожалуйста, введите корректное короткое описание."))
        return

    await handle_set_bot_description(description, message, state, bot)
