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 configs import COMMANDS
from middleware.loggers import logger

__all__ = ("router",)
CMD: str = "set_name".lower()
router: Router = Router(name=f"{CMD}_cmd_router")


class SetNameForm(StatesGroup):
    new_name: State = State()


def format_retry_time(retry_after: int) -> str:
    """Форматирование времени повторной попытки в читаемом виде"""
    hours, remainder = divmod(retry_after, 3600)
    minutes, seconds = divmod(remainder, 60)

    if hours > 0:
        return f"{hours} часов, {minutes} минут, {seconds} секунд"
    elif minutes > 0:
        return f"{minutes} минут, {seconds} секунд"
    else:
        return f"{seconds} секунд"


async def handle_set_name(
        new_name: str,
        message: Message | CallbackQuery,
        state: FSMContext,
        bot: Bot
) -> None:
    """
    Установка имени бота с проверкой длины, обработкой перегрузки и логированием
    """
    if len(new_name) > 64:
        await msg(
            message=message,
            text=_("❌ Имя бота должно быть не более 64 символов. Текущая длина: {length}").format(
                length=len(new_name)
            ),
            markup=settings_keyboard(),
        )
        return

    try:
        await bot.set_my_name(new_name)
        BotInfo.first_name = new_name
        await state.clear()
        await msg(
            message=message,
            text=_("✅ Имя бота успешно изменено на: <b>{new_name}</b>").format(new_name=new_name),
            markup=settings_keyboard(),
        )
        logger.info(f"Имя бота изменено на: {new_name}")

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

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

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


@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
):
    """
    Обработчик команды /set_name с поддержкой:
        1. Immediate установки через аргумент команды
        2. Callback query
        3. FSM ввод
    """
    current_name = getattr(BotInfo, "first_name", "") or _("Не установлено")

    # Immediate установка через аргумент команды
    if command and command.args:
        new_name = command.args.strip()
        if len(new_name) > 64:
            await msg(
                message=message,
                text=_("❌ Имя не должно превышать 64 символа. Текущая длина: {length}").format(
                    length=len(new_name)
                ),
                markup=settings_keyboard(),
            )
            return
        await handle_set_name(new_name, message, state, bot)
        return

    # Для callback query или пустой команды — показываем текущее имя и запускаем FSM
    await state.clear()
    if isinstance(message, CallbackQuery):
        await message.answer()
    text: str = _(
        "🤖 <b>Смена имени бота</b>\n\n"
        "Текущее имя: <i>{current}</i>\n\n"
        "Пожалуйста, введите новое имя для бота (максимум 64 символа):"
    ).format(current=current_name)
    await msg(message=message, text=text, markup=settings_keyboard())
    await state.set_state(SetNameForm.new_name)


@router.message(SetNameForm.new_name, IsOwner())
async def process_new_name(message: Message, state: FSMContext, bot: Bot):
    """
    Обработка ввода нового имени через FSM
    """
    new_name: str = message.text.strip()

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

    await handle_set_name(new_name, message, state, bot)
