from __future__ import annotations

from typing import Iterable

from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.enums import MessageEntityType
from aiogram.types import CallbackQuery, Message, MessageEntity
from aiogram.utils.keyboard import InlineKeyboardBuilder

from filters.admin import IsAdminFilter
from handlers.buttons import BACK
from ..panel.keyboard import AdminPanelCallback, build_admin_back_kb


class AdminEmojiState(StatesGroup):
    waiting_for_custom_emoji = State()


router = Router()


def _build_back_to_emoji_menu() -> InlineKeyboardBuilder:
    builder = InlineKeyboardBuilder()
    builder.button(text=BACK, callback_data=AdminPanelCallback(action="emoji").pack())
    builder.adjust(1)
    return builder


def _extract_custom_emoji_ids(entities: Iterable[MessageEntity]) -> list[str]:
    ids: list[str] = []
    for ent in entities:
        if ent.type == MessageEntityType.CUSTOM_EMOJI and ent.custom_emoji_id:
            ids.append(ent.custom_emoji_id)
    return ids


def _utf16_len(text: str) -> int:
    return len(text.encode("utf-16-le")) // 2


@router.callback_query(AdminPanelCallback.filter(F.action == "emoji"), IsAdminFilter())
async def show_emoji_menu(callback_query: CallbackQuery, state: FSMContext):
    await state.set_state(AdminEmojiState.waiting_for_custom_emoji)
    example_id = "5201769509345588200"
    marker = f"{{{{emoji:{example_id}}}}}"
    preview_placeholder = "😀"
    text = (
        "Отправьте любое кастомное эмоджи — я верну его ID и покажу пример для текстов.\n\n"
        "Пример:\n"
        f"{preview_placeholder}"
    )

    entities: list[MessageEntity] = []
    start = 0
    while True:
        marker_pos = text.find(marker, start)
        if marker_pos == -1:
            break
        entities.append(
            MessageEntity(
                type=MessageEntityType.CODE,
                offset=_utf16_len(text[:marker_pos]),
                length=_utf16_len(marker),
            )
        )
        start = marker_pos + len(marker)
    preview_pos = text.find(preview_placeholder)
    if preview_pos != -1:
        entities.append(
            MessageEntity(
                type=MessageEntityType.CUSTOM_EMOJI,
                offset=_utf16_len(text[:preview_pos]),
                length=_utf16_len(preview_placeholder),
                custom_emoji_id=example_id,
            )
        )

    if hasattr(callback_query.message, "_original_edit_text"):
        await callback_query.message._original_edit_text(
            text=text,
            entities=entities,
            reply_markup=build_admin_back_kb("admin"),
            parse_mode=None,
        )
    else:
        await callback_query.message.edit_text(
            text=text,
            entities=entities,
            reply_markup=build_admin_back_kb("admin"),
            parse_mode=None,
        )


@router.message(AdminEmojiState.waiting_for_custom_emoji, IsAdminFilter())
async def handle_custom_emoji_id(message: Message, state: FSMContext):
    entities = list(message.entities or []) + list(message.caption_entities or [])
    emoji_ids = _extract_custom_emoji_ids(entities)

    if not emoji_ids:
        await message.answer(
            "❌ Не вижу кастомных эмоджи. Отправьте именно <b>кастомный эмоджи</b> из набора.",
            reply_markup=_build_back_to_emoji_menu().as_markup(),
        )
        return

    unique_ids: list[str] = []
    for emoji_id in emoji_ids:
        if emoji_id not in unique_ids:
            unique_ids.append(emoji_id)

    placeholder = "😀"
    back_builder = _build_back_to_emoji_menu()

    if len(unique_ids) == 1:
        emoji_id = unique_ids[0]
        marker = f"{{{{emoji:{emoji_id}}}}}"
        example_send = f"Ты отправил: Привет, {marker} !"
        example_recv = f"А получил: Привет, {placeholder} !"
        instruction_text = (
            "✅ ID кастомного эмоджи\n"
            f"{emoji_id}\n\n"
            "Вставляйте в файл текстов так:\n"
            f"{marker}\n\n"
            "Пример:\n"
            f"{example_send}\n"
            f"{example_recv}\n\n"
            "⚠️ Условие: отображение кастомных эмоджи работает, если у владельца бота есть Telegram Premium."
        )
        preview_text = example_recv
        preview_ids = [emoji_id]
        code_markers = [marker]
    else:
        ids_text = "\n".join(f"• {emoji_id}" for emoji_id in unique_ids)
        markers_text = "\n".join(f"• {{{{emoji:{emoji_id}}}}}" for emoji_id in unique_ids)
        markers_inline = " ".join(f"{{{{emoji:{emoji_id}}}}}" for emoji_id in unique_ids)
        example_send = f"Ты отправил: Привет, {markers_inline} !"
        example_recv = "А получил: Привет, " + " ".join(placeholder for _ in unique_ids) + " !"
        instruction_text = (
            "✅ ID кастомных эмоджи\n"
            f"{ids_text}\n\n"
            "Вставляйте в файл текстов так:\n"
            f"{markers_text}\n\n"
            "Пример:\n"
            f"{example_send}\n"
            f"{example_recv}\n\n"
            "⚠️ Условие: отображение кастомных эмоджи работает, если у владельца бота есть Telegram Premium."
        )
        preview_text = example_recv
        preview_ids = unique_ids
        code_markers = [f"{{{{emoji:{emoji_id}}}}}" for emoji_id in unique_ids]

    full_text = instruction_text

    entities: list[MessageEntity] = []
    for marker in code_markers:
        start = 0
        while True:
            pos = full_text.find(marker, start)
            if pos == -1:
                break
            entities.append(
                MessageEntity(
                    type=MessageEntityType.CODE,
                    offset=_utf16_len(full_text[:pos]),
                    length=_utf16_len(marker),
                )
            )
            start = pos + len(marker)

    for emoji_id in unique_ids:
        start = 0
        while True:
            pos = full_text.find(emoji_id, start)
            if pos == -1:
                break
            entities.append(
                MessageEntity(
                    type=MessageEntityType.CODE,
                    offset=_utf16_len(full_text[:pos]),
                    length=_utf16_len(emoji_id),
                )
            )
            start = pos + len(emoji_id)
    preview_offset_base = _utf16_len(full_text[: full_text.index(preview_text)])
    running_utf16 = 0
    idx = 0
    for ch in preview_text:
        if ch == placeholder and idx < len(preview_ids):
            entities.append(
                MessageEntity(
                    type=MessageEntityType.CUSTOM_EMOJI,
                    offset=preview_offset_base + running_utf16,
                    length=_utf16_len(placeholder),
                    custom_emoji_id=str(preview_ids[idx]),
                )
            )
            idx += 1
        running_utf16 += _utf16_len(ch)

    if hasattr(message, "_original_answer"):
        await message._original_answer(
            text=full_text,
            entities=entities,
            reply_markup=back_builder.as_markup(),
            parse_mode=None,
        )
    else:
        await message.answer(text=full_text, reply_markup=back_builder.as_markup(), parse_mode=None)
    await state.clear()
