"""
Admin Handlers
"""
import json
import html
import re
from aiogram import Router, F, types
from aiogram.types import CallbackQuery, Message, InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.enums import MessageEntityType
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from database.db_manager import UserManager, PlansManager, TransactionManager, UISettingsManager, OrderManager
from utils.messages import MessageTemplates
from utils.keyboard_builder import AdvancedKeyboard
from utils.raw_sender import send_or_edit_with_raw_keyboard
from config.settings import (
    USERS_DB,
    PLANS_DB,
    TRANSACTIONS_DB,
    UI_SETTINGS_DB,
    ORDERS_DB,
    ADMIN_ID,
    EMOJI_CHECK,
    EMOJI_FIRE,
    EMOJI_GIFT,
)

router = Router()
user_manager = UserManager(USERS_DB)
plans_manager = PlansManager(PLANS_DB)
transaction_manager = TransactionManager(TRANSACTIONS_DB)
ui_settings_manager = UISettingsManager(UI_SETTINGS_DB)
order_manager = OrderManager(ORDERS_DB)


class AdminStates(StatesGroup):
    """Admin FSM States"""
    broadcast_message = State()
    new_plan_name = State()
    new_plan_volume = State()
    new_plan_price = State()
    find_user = State()
    charge_amount = State()
    charge_user = State()
    ui_welcome_text = State()
    ui_welcome_buttons = State()
    ui_extract_emoji = State()
    force_join_targets = State()
    force_join_toggle = State()
    dm_user_id = State()
    dm_text = State()
    complete_order_link = State()
    manual_points_user_id = State()
    manual_points_user_amount = State()
    manual_points_all_amount = State()
    ui_order_template_text = State()
    edit_plan_payload = State()


def _extract_custom_emoji_ids(message: Message) -> list[str]:
    """Extract unique custom emoji IDs from message entities."""
    entities = message.entities or message.caption_entities or []
    emoji_ids: list[str] = []
    for entity in entities:
        if entity.type == MessageEntityType.CUSTOM_EMOJI and entity.custom_emoji_id:
            if entity.custom_emoji_id not in emoji_ids:
                emoji_ids.append(entity.custom_emoji_id)
    return emoji_ids


def _utf16_to_py_index_map(text: str) -> list[int]:
    """Build map from UTF-16 code unit offsets to Python string indices."""
    mapping: list[int] = []
    for idx, ch in enumerate(text):
        units = 2 if ord(ch) > 0xFFFF else 1
        for _ in range(units):
            mapping.append(idx)
    mapping.append(len(text))
    return mapping


def _convert_message_to_html_with_custom_emoji(message: Message) -> str:
    """Convert Telegram message text to HTML and keep premium emoji as tg-emoji tags."""
    text = message.text or message.caption or ""
    if not text:
        return ""

    # If admin already authored HTML/tg-emoji tags, keep them untouched.
    # Escaping here would break animated premium emoji tags.
    if "<" in text and ">" in text:
        return _normalize_tg_emoji_html(text)

    entities = message.entities or message.caption_entities or []
    custom_entities = [
        e for e in entities
        if e.type == MessageEntityType.CUSTOM_EMOJI and e.custom_emoji_id
    ]

    if not custom_entities:
        return text

    custom_entities = sorted(custom_entities, key=lambda e: e.offset)
    mapping = _utf16_to_py_index_map(text)

    out_parts: list[str] = []
    cursor = 0
    for entity in custom_entities:
        start_u16 = entity.offset
        end_u16 = entity.offset + entity.length
        if start_u16 >= len(mapping):
            continue
        if end_u16 >= len(mapping):
            end_u16 = len(mapping) - 1

        start = mapping[start_u16]
        end = mapping[end_u16]
        if start < cursor:
            continue

        out_parts.append(html.escape(text[cursor:start]))
        emoji_text = html.escape(text[start:end]) or "🙂"
        out_parts.append(
            f'<tg-emoji emoji-id="{entity.custom_emoji_id}">{emoji_text}</tg-emoji>'
        )
        cursor = end

    out_parts.append(html.escape(text[cursor:]))
    return _normalize_tg_emoji_html("".join(out_parts))


def _strip_tg_emoji_tags(text: str) -> str:
    """Remove tg-emoji tags while keeping visible fallback emoji/text inside them."""
    no_wrapped = re.sub(r'<tg-emoji\b[^>]*>(.*?)</tg-emoji>', r'\1', text, flags=re.IGNORECASE | re.DOTALL)
    no_open = re.sub(r'<tg-emoji\b[^>]*>', '', no_wrapped, flags=re.IGNORECASE)
    return no_open.replace('</tg-emoji>', '')


def _normalize_tg_emoji_html(text: str) -> str:
    """Normalize HTML for reliable tg-emoji rendering in Telegram clients."""
    normalized = text

    if "&lt;" in normalized and "&gt;" in normalized:
        normalized = html.unescape(normalized)

    normalized = re.sub(r'^\s*<pre>\s*', '', normalized, flags=re.IGNORECASE)
    normalized = re.sub(r'\s*</pre>\s*$', '', normalized, flags=re.IGNORECASE)

    normalized = re.sub(
        r"(<tg-emoji\\b[^>]*emoji-id=)'([^']+)'",
        r'\\1"\\2"',
        normalized,
        flags=re.IGNORECASE,
    )
    normalized = re.sub(
        r'(<tg-emoji\\b[^>]*emoji-id=)[“”‘’]([^“”‘’]+)[“”‘’]',
        r'\\1"\\2"',
        normalized,
        flags=re.IGNORECASE,
    )
    return normalized


def _get_welcome_buttons_or_default() -> list:
    """Return editable welcome buttons payload, fallback to colored main menu payload."""
    payload = ui_settings_manager.get_welcome_buttons()
    if isinstance(payload, list) and payload:
        return payload
    return AdvancedKeyboard.main_menu_payload().get('inline_keyboard', [])


def _build_button_index_keyboard(buttons_payload: list) -> InlineKeyboardMarkup:
    """Create keyboard to choose which button style to change."""
    rows = []
    for r_idx, row in enumerate(buttons_payload):
        for c_idx, btn in enumerate(row):
            style = btn.get('style', 'primary')
            text = btn.get('text', f'دکمه {r_idx + 1}-{c_idx + 1}')
            rows.append([
                InlineKeyboardButton(
                    text=f"{text} ({style})",
                    callback_data=f"admin_ui_pick_color_{r_idx}_{c_idx}",
                )
            ])
    rows.append([InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_ui")])
    return InlineKeyboardMarkup(inline_keyboard=rows)


def _build_color_picker_keyboard(row_idx: int, col_idx: int) -> InlineKeyboardMarkup:
    """Color picker keyboard for selected button."""
    return InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text="🟢 سبز",
                    callback_data=f"admin_ui_set_color_{row_idx}_{col_idx}_success",
                ),
                InlineKeyboardButton(
                    text="🔵 آبی",
                    callback_data=f"admin_ui_set_color_{row_idx}_{col_idx}_primary",
                ),
            ],
            [
                InlineKeyboardButton(
                    text="🔴 قرمز",
                    callback_data=f"admin_ui_set_color_{row_idx}_{col_idx}_danger",
                )
            ],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_ui_color_buttons")],
        ]
    )


async def is_admin(user_id: int) -> bool:
    """Check if user is admin"""
    return user_id == ADMIN_ID


@router.message(Command("admin"))
async def admin_panel(message: Message):
    """Show admin panel"""
    if not await is_admin(message.from_user.id):
        await message.answer("❌ شما ادمین نیستید!")
        return
    
    text = """
    👑 <b>پنل مدیریت</b>
    
    خوش‌آمدید ادمین!
    """
    
    await send_or_edit_with_raw_keyboard(
        chat_id=message.chat.id,
        text=text,
        reply_markup=AdvancedKeyboard.admin_panel_payload(),
    )


@router.callback_query(F.data == "admin_stats")
async def admin_stats(callback: CallbackQuery):
    """Show admin stats"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    all_users = user_manager.get_all_users()
    active_users = user_manager.get_active_users_count()
    total_sales = transaction_manager.get_total_sales()
    total_referrals = sum(u['referrals_count'] for u in all_users)
    
    text = MessageTemplates.admin_stats(
        len(all_users),
        active_users,
        total_sales,
        total_referrals
    )
    
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")]
    ])
    
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_plans")
async def admin_plans(callback: CallbackQuery):
    """Manage plans"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    plans = plans_manager.get_all_plans()
    
    text = "🛍️ <b>مدیریت پلن‌ها</b>\n\n"
    for plan in plans:
        text += f"""
<b>{plan['name']}</b>
├─ حجم: {plan['volume_gb']} GB
├─ مدت: {plan['duration_days']} روز
├─ قیمت: {plan['price_toman']:,} تومان
└─ وضعیت: {'✅ فعال' if plan['active'] else '❌ غیرفعال'}

"""
    
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="➕ پلن جدید", callback_data="admin_new_plan")],
        [InlineKeyboardButton(text="✏️ ویرایش پلن", callback_data="admin_edit_plan")],
        [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")]
    ])
    
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_new_plan")
async def admin_new_plan(callback: CallbackQuery, state: FSMContext):
    """Start new plan creation flow."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    await state.set_state(AdminStates.new_plan_name)
    await callback.message.edit_text(
        "➕ <b>ایجاد پلن جدید</b>\n\n"
        "نام پلن را ارسال کنید:",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_plans")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.new_plan_name)
async def admin_new_plan_get_name(message: Message, state: FSMContext):
    """Receive new plan name."""
    name = (message.text or "").strip()
    if not name:
        await message.answer("❌ نام پلن نمی‌تواند خالی باشد")
        return
    await state.update_data(new_plan_name=name)
    await state.set_state(AdminStates.new_plan_volume)
    await message.answer("📦 حجم پلن را بر حسب GB ارسال کنید (مثال: 50)")


@router.message(AdminStates.new_plan_volume)
async def admin_new_plan_get_volume(message: Message, state: FSMContext):
    """Receive new plan volume."""
    try:
        volume = int((message.text or "").strip())
        if volume <= 0:
            raise ValueError
    except ValueError:
        await message.answer("❌ حجم معتبر نیست")
        return

    await state.update_data(new_plan_volume=volume)
    await state.set_state(AdminStates.new_plan_price)
    await message.answer("💵 قیمت پلن را به تومان ارسال کنید (مثال: 250000)")


@router.message(AdminStates.new_plan_price)
async def admin_new_plan_get_price(message: Message, state: FSMContext):
    """Receive new plan price and create plan."""
    try:
        price_toman = int((message.text or "").strip())
        if price_toman <= 0:
            raise ValueError
    except ValueError:
        await message.answer("❌ قیمت معتبر نیست")
        return

    data = await state.get_data()
    name = data.get('new_plan_name')
    volume = data.get('new_plan_volume')
    if not name or not volume:
        await message.answer("❌ اطلاعات پلن ناقص است")
        await state.clear()
        return

    plan_data = {
        'name': str(name),
        'volume_gb': int(volume),
        'duration_days': 30,
        'price_toman': int(price_toman),
        'price_usdt': round(int(price_toman) / 90000, 2),
        'description': 'پلن ایجاد شده توسط ادمین',
    }
    plans_manager.create_plan(plan_data)
    await message.answer(
        "✅ پلن جدید ساخته شد\n\n"
        f"نام: <b>{html.escape(str(name))}</b>\n"
        f"حجم: <code>{volume} GB</code>\n"
        f"قیمت: <code>{price_toman:,}</code> تومان",
        parse_mode="HTML",
    )
    await state.clear()


@router.callback_query(F.data == "admin_edit_plan")
async def admin_edit_plan(callback: CallbackQuery):
    """Show plans list for editing."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    plans = plans_manager.get_all_plans()
    if not plans:
        await callback.answer("پلنی برای ویرایش وجود ندارد", show_alert=True)
        return

    rows = []
    for plan in plans:
        rows.append([
            InlineKeyboardButton(
                text=f"✏️ {plan['name']} ({plan['volume_gb']}GB)",
                callback_data=f"admin_edit_plan_pick_{plan['id']}",
            )
        ])
    rows.append([InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_plans")])

    await callback.message.edit_text(
        "✏️ <b>ویرایش پلن</b>\n\n"
        "یک پلن را انتخاب کن:",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows),
        parse_mode="HTML",
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_edit_plan_pick_"))
async def admin_edit_plan_pick(callback: CallbackQuery, state: FSMContext):
    """Pick plan and ask for new values in one line."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    plan_id = callback.data.split("_")[-1]
    plan = plans_manager.get_plan(plan_id)
    if not plan:
        await callback.answer("پلن پیدا نشد", show_alert=True)
        return

    await state.update_data(edit_plan_id=plan_id)
    await state.set_state(AdminStates.edit_plan_payload)
    await callback.message.edit_text(
        "🛠️ <b>ویرایش پلن</b>\n\n"
        f"پلن فعلی: <b>{html.escape(plan['name'])}</b>\n"
        f"حجم فعلی: <code>{plan.get('volume_gb')}</code> GB\n"
        f"قیمت فعلی: <code>{plan.get('price_toman')}</code> تومان\n"
        f"مدت فعلی: <code>{plan.get('duration_days')}</code> روز\n\n"
        "مقادیر جدید را به این فرمت بفرست:\n"
        "<code>نام|حجمGB|قیمتتومان|مدتروز</code>\n"
        "مثال:\n"
        "<code>پریمیوم ویژه|100|320000|30</code>",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_plans")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.edit_plan_payload)
async def admin_edit_plan_save(message: Message, state: FSMContext):
    """Save edited plan fields."""
    raw = (message.text or "").strip()
    parts = [p.strip() for p in raw.split("|")]
    if len(parts) != 4:
        await message.answer("❌ فرمت ورودی نامعتبر است. باید 4 بخش با | ارسال شود")
        return

    name, volume_s, price_s, duration_s = parts
    try:
        volume = int(volume_s)
        price_toman = int(price_s)
        duration_days = int(duration_s)
        if volume <= 0 or price_toman <= 0 or duration_days <= 0:
            raise ValueError
    except ValueError:
        await message.answer("❌ حجم/قیمت/مدت باید عدد مثبت باشد")
        return

    data = await state.get_data()
    plan_id = str(data.get('edit_plan_id', ''))
    if not plan_id:
        await message.answer("❌ شناسه پلن پیدا نشد")
        await state.clear()
        return

    plans_manager.update_plan(
        plan_id,
        {
            'name': name,
            'volume_gb': volume,
            'price_toman': price_toman,
            'price_usdt': round(price_toman / 90000, 2),
            'duration_days': duration_days,
        },
    )
    await message.answer(
        "✅ پلن با موفقیت ویرایش شد\n\n"
        f"ID: <code>{plan_id}</code>\n"
        f"نام: <b>{html.escape(name)}</b>\n"
        f"حجم: <code>{volume} GB</code>\n"
        f"قیمت: <code>{price_toman:,}</code> تومان\n"
        f"مدت: <code>{duration_days}</code> روز",
        parse_mode="HTML",
    )
    await state.clear()


@router.callback_query(F.data == "admin_orders")
async def admin_orders(callback: CallbackQuery):
    """Show pending orders and let admin complete them."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    pending = order_manager.get_pending_orders()
    if not pending:
        await callback.message.edit_text(
            "📦 <b>مدیریت سفارشات</b>\n\nسفارش در انتظار وجود ندارد.",
            reply_markup=InlineKeyboardMarkup(
                inline_keyboard=[[InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")]]
            ),
            parse_mode="HTML",
        )
        await callback.answer()
        return

    text = "📦 <b>سفارشات در انتظار</b>\n\n"
    kb_rows = []
    for order in pending[:30]:
        text += (
            f"• سفارش <code>#{order['id']}</code> | کاربر: <code>{order['user_id']}</code> | "
            f"نوع: <code>{order['order_type']}</code>\n"
        )
        kb_rows.append([
            InlineKeyboardButton(
                text=f"تکمیل سفارش #{order['id']}",
                callback_data=f"admin_complete_order_{order['id']}",
            )
        ])
    kb_rows.append([InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")])
    await callback.message.edit_text(
        text,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=kb_rows),
        parse_mode="HTML",
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_complete_order_"))
async def admin_complete_order(callback: CallbackQuery, state: FSMContext):
    """Ask admin to send config/filter link for selected order."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    order_id = callback.data.split("_")[-1]
    order = order_manager.get_order(order_id)
    if not order or order.get('status') != 'pending':
        await callback.answer("سفارش معتبر نیست یا تکمیل شده", show_alert=True)
        return

    await state.set_state(AdminStates.complete_order_link)
    await state.update_data(complete_order_id=order_id)
    await callback.message.edit_text(
        "✅ <b>تکمیل سفارش</b>\n\n"
        f"شماره سفارش: <code>{order_id}</code>\n"
        f"آیدی کاربر: <code>{order['user_id']}</code>\n\n"
        "حالا اطلاعات را ارسال کنید به این فرمت:\n"
        "<code>line1: لینک کانفیگ/فیلتر\n"
        "line2: حجم (اختیاری) مثل 50GB\n"
        "line3+: توضیحات (اختیاری)</code>",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_orders")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.complete_order_link)
async def admin_complete_order_link(message: Message, state: FSMContext):
    """Complete order and send config/filter link to user."""
    data = await state.get_data()
    order_id = str(data.get('complete_order_id', ''))
    order = order_manager.get_order(order_id)
    if not order or order.get('status') != 'pending':
        await message.answer("❌ سفارش پیدا نشد یا قبلا تکمیل شده")
        await state.clear()
        return

    raw = (message.text or message.caption or "").strip()
    if not raw:
        await message.answer("❌ لینک یا متن تکمیل سفارش را ارسال کنید (یا همراه مدیا کپشن بگذارید)")
        return

    lines = [ln.strip() for ln in raw.splitlines() if ln.strip()]
    config_link = lines[0]
    input_volume = lines[1] if len(lines) > 1 else ""
    extra_note = "\n".join(lines[2:]) if len(lines) > 2 else ""

    # Fallback to plan volume when admin does not send explicit volume.
    plan = plans_manager.get_plan(str(order.get('plan_id', '')))
    plan_volume = f"{plan.get('volume_gb')} GB" if plan and plan.get('volume_gb') else "نامشخص"
    delivery_volume = input_volume if input_volume else plan_volume
    done = order_manager.complete_order(order_id, message.from_user.id, config_link)
    if not done:
        await message.answer("❌ تکمیل سفارش ناموفق بود")
        await state.clear()
        return

    user_id = int(order['user_id'])
    delivery_warning = ""
    try:
        safe_link = html.escape(config_link)
        safe_volume = html.escape(delivery_volume)
        safe_note = html.escape(extra_note)
        default_tpl = (
            f'<tg-emoji emoji-id="{EMOJI_FIRE}">🔥</tg-emoji> <b>سفارش شما تکمیل شد</b>\n\n'
            f'<tg-emoji emoji-id="{EMOJI_FIRE}">🔥</tg-emoji> شماره سفارش: <code>{order_id}</code>\n'
            f'<tg-emoji emoji-id="{EMOJI_GIFT}">🎁</tg-emoji> حجم سرویس: <code>{delivery_volume}</code>\n'
            f'<tg-emoji emoji-id="{EMOJI_GIFT}">🎁</tg-emoji> لینک کانفیگ/فیلتر:\n'
            f'<code>{config_link}</code>\n\n'
            f'📝 <b>توضیحات:</b>\n'
            f'{extra_note}'
        )
        default_pretty_text = (
            f'<tg-emoji emoji-id="{EMOJI_FIRE}">🔥</tg-emoji> <b>سفارش شما تکمیل شد</b>\n\n'
            f'<tg-emoji emoji-id="{EMOJI_FIRE}">🔥</tg-emoji> شماره سفارش: <code>{order_id}</code>\n'
            f'<tg-emoji emoji-id="{EMOJI_GIFT}">🎁</tg-emoji> حجم سرویس: <code>{safe_volume}</code>\n'
            f'<tg-emoji emoji-id="{EMOJI_GIFT}">🎁</tg-emoji> لینک کانفیگ/فیلتر:\n'
            f'<code>{safe_link}</code>'
            + (f'\n\n📝 <b>توضیحات:</b>\n{safe_note}' if extra_note else '')
        )
        template = ui_settings_manager.get_text_template('user_order_completed', default_tpl)
        context = {
            'order_id': order_id,
            'user_id': user_id,
            'full_name': message.from_user.full_name if message.from_user else '',
            'username': f"@{message.from_user.username}" if message.from_user and message.from_user.username else 'ندارد',
            'order_type': order.get('order_type', ''),
            'currency': order.get('currency', ''),
            'amount': order.get('amount', ''),
            'plan_id': order.get('plan_id', ''),
            'volume': delivery_volume,
            'link': config_link,
            'note': extra_note,
        }
        has_placeholders = any(
            ph in template for ph in [
                '{order_id}', '{user_id}', '{full_name}', '{username}',
                '{order_type}', '{currency}', '{amount}', '{plan_id}',
                '{volume}', '{link}', '{note}'
            ]
        )
        pretty_text = template
        for k, v in context.items():
            pretty_text = pretty_text.replace(f"{{{k}}}", html.escape(str(v)))

        # If admin wrote a plain template without placeholders, append core order data.
        if not has_placeholders:
            pretty_text += (
                "\n\n"
                f"<b>شماره سفارش:</b> <code>{html.escape(str(order_id))}</code>\n"
                f"<b>حجم سرویس:</b> <code>{safe_volume}</code>\n"
                f"<b>لینک/متن:</b>\n<code>{safe_link}</code>"
                + (f"\n\n<b>توضیحات:</b>\n{safe_note}" if extra_note else "")
            )

        # Always send formatted text first so delivery never depends on media validity.
        try:
            await message.bot.send_message(
                user_id,
                pretty_text,
                parse_mode="HTML",
            )
        except TelegramBadRequest as tpl_exc:
            # If premium emoji IDs are invalid, retry custom template without tg-emoji tags.
            tpl_exc_text = str(tpl_exc)
            custom_sent_without_premium = False
            if "DOCUMENT_INVALID" in tpl_exc_text.upper():
                try:
                    await message.bot.send_message(
                        user_id,
                        _strip_tg_emoji_tags(pretty_text),
                        parse_mode="HTML",
                    )
                    custom_sent_without_premium = True
                    await message.answer(
                        "⚠️ قالب سفارشی user_order_completed با emoji-id نامعتبر خطا داد؛ همان قالب بدون پرمیوم ارسال شد.",
                    )
                except TelegramBadRequest:
                    custom_sent_without_premium = False

            if custom_sent_without_premium:
                tpl_exc = None
            # Try known-good premium default template before plain text fallback.
            if tpl_exc is None:
                pass
            else:
                try:
                    await message.bot.send_message(
                        user_id,
                        default_pretty_text,
                        parse_mode="HTML",
                    )
                    await message.answer(
                        "⚠️ قالب سفارشی user_order_completed خطا داشت؛ با قالب پرمیوم پیش‌فرض ارسال شد.\n"
                        f"<code>{html.escape(str(tpl_exc))}</code>",
                        parse_mode="HTML",
                    )
                except TelegramBadRequest as default_exc:
                    # If default premium template has invalid emoji-id too, retry it without premium tags.
                    default_exc_text = str(default_exc)
                    if "DOCUMENT_INVALID" in default_exc_text.upper():
                        try:
                            await message.bot.send_message(
                                user_id,
                                _strip_tg_emoji_tags(default_pretty_text),
                                parse_mode="HTML",
                            )
                            await message.answer(
                                "⚠️ هم قالب سفارشی و هم پیش‌فرض به‌خاطر emoji-id نامعتبر خطا دادند؛ قالب پیش‌فرض بدون پرمیوم ارسال شد.\n"
                                f"custom: <code>{html.escape(str(tpl_exc))}</code>\n"
                                f"default: <code>{html.escape(str(default_exc))}</code>",
                                parse_mode="HTML",
                            )
                        except TelegramBadRequest as default_no_emoji_exc:
                            # Final fallback: plain text without HTML entities/tags.
                            plain_text = (
                                "سفارش شما تکمیل شد\n\n"
                                f"شماره سفارش: {order_id}\n"
                                f"حجم سرویس: {delivery_volume}\n"
                                f"لینک/متن: {config_link}"
                                + (f"\n\nتوضیحات:\n{extra_note}" if extra_note else "")
                            )
                            await message.bot.send_message(user_id, plain_text)
                            await message.answer(
                                "⚠️ قالب سفارشی، پیش‌فرض پرمیوم و پیش‌فرض بدون پرمیوم همگی خطا داشتند؛ به‌صورت متن ساده ارسال شد.\n"
                                f"custom: <code>{html.escape(str(tpl_exc))}</code>\n"
                                f"default: <code>{html.escape(str(default_exc))}</code>\n"
                                f"default_no_premium: <code>{html.escape(str(default_no_emoji_exc))}</code>",
                                parse_mode="HTML",
                            )
                    else:
                        # Final fallback: plain text without HTML entities/tags.
                        plain_text = (
                            "سفارش شما تکمیل شد\n\n"
                            f"شماره سفارش: {order_id}\n"
                            f"حجم سرویس: {delivery_volume}\n"
                            f"لینک/متن: {config_link}"
                            + (f"\n\nتوضیحات:\n{extra_note}" if extra_note else "")
                        )
                        await message.bot.send_message(user_id, plain_text)
                        await message.answer(
                            "⚠️ هم قالب سفارشی و هم قالب پیش‌فرض پرمیوم خطا داشت؛ به‌صورت متن ساده ارسال شد.\n"
                            f"custom: <code>{html.escape(str(tpl_exc))}</code>\n"
                            f"default: <code>{html.escape(str(default_exc))}</code>",
                            parse_mode="HTML",
                        )

        # If admin provided media, try copying it as an extra message.
        if message.photo or message.video or message.document or message.audio or message.voice:
            try:
                await message.bot.copy_message(
                    chat_id=user_id,
                    from_chat_id=message.chat.id,
                    message_id=message.message_id,
                )
            except Exception as media_exc:
                # Do not fail whole completion because media copy can fail on invalid files.
                delivery_warning = f"\n⚠️ فقط مدیا ارسال نشد: <code>{html.escape(str(media_exc))}</code>"
    except Exception as exc:
        await message.answer(f"⚠️ سفارش تکمیل شد ولی ارسال متن به کاربر خطا داشت: {exc}")
        await state.clear()
        return

    await message.answer(f"✅ سفارش #{order_id} تکمیل شد و متن برای کاربر ارسال شد{delivery_warning}", parse_mode="HTML")
    await state.clear()


@router.callback_query(F.data == "admin_users")
async def admin_users(callback: CallbackQuery, state: FSMContext):
    """Manage users"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    text = """
    👥 <b>مدیریت کاربران</b>
    
    شماره کاربری کاربری را وارد کنید:
    """
    
    await state.set_state(AdminStates.find_user)
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="❌ انصراف", callback_data="admin_back")]
    ])
    
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.message(AdminStates.find_user)
async def find_user(message: Message, state: FSMContext):
    """Find user by ID"""
    try:
        user_id = int(message.text)
        user = user_manager.get_user(user_id)
        
        if not user:
            await message.answer("❌ کاربر یافت نشد!")
            return
        
        text = MessageTemplates.admin_user_found(user)
        
        kb = InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🚫 مسدود کردن", callback_data=f"admin_block_{user_id}")],
            [InlineKeyboardButton(text="✅ آزاد کردن", callback_data=f"admin_unblock_{user_id}")],
            [InlineKeyboardButton(text="💰 شارژ", callback_data=f"admin_charge_{user_id}")],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_users")]
        ])
        
        await message.answer(text, reply_markup=kb, parse_mode="HTML")
        await state.clear()
    except ValueError:
        await message.answer("❌ شماره کاربری نامعتبر است!")


@router.callback_query(F.data.startswith("admin_block_"))
async def admin_block_user(callback: CallbackQuery):
    """Block user"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    user_id = int(callback.data.split("_")[-1])
    user_manager.block_user(user_id)
    
    await callback.answer("✅ کاربر مسدود شد", show_alert=True)


@router.callback_query(F.data.startswith("admin_unblock_"))
async def admin_unblock_user(callback: CallbackQuery):
    """Unblock user"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    user_id = int(callback.data.split("_")[-1])
    user_manager.unblock_user(user_id)
    
    await callback.answer("✅ کاربر آزاد شد", show_alert=True)


@router.callback_query(F.data.startswith("admin_charge_"))
async def admin_charge_user(callback: CallbackQuery, state: FSMContext):
    """Charge user wallet"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    user_id = int(callback.data.split("_")[-1])
    await state.update_data(charge_user_id=user_id)
    await state.set_state(AdminStates.charge_amount)
    
    text = "💰 <b>شارژ کاربر</b>\n\nمبلغ را برحسب تومان وارد کنید:"
    
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="❌ انصراف", callback_data="admin_back")]
    ])
    
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_charge")
async def admin_charge_menu(callback: CallbackQuery):
    """Manual charge menu for toman and points."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    text = (
        "💳 <b>شارژ دستی</b>\n\n"
        "نوع شارژ موردنظر را انتخاب کنید:"
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text="💵 شارژ تومان یک کاربر", callback_data="admin_users")],
            [InlineKeyboardButton(text="🪙 امتیاز دستی یک کاربر", callback_data="admin_points_user")],
            [InlineKeyboardButton(text="🌍 امتیاز دستی همه کاربران", callback_data="admin_points_all")],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")],
        ]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_points_user")
async def admin_points_user_start(callback: CallbackQuery, state: FSMContext):
    """Start manual points assignment for a single user."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    await state.set_state(AdminStates.manual_points_user_id)
    await callback.message.edit_text(
        "🪙 <b>امتیاز دستی یک کاربر</b>\n\n"
        "آیدی عددی کاربر را ارسال کنید:",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_charge")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.manual_points_user_id)
async def admin_points_user_get_id(message: Message, state: FSMContext):
    """Receive target user id for manual points."""
    try:
        user_id = int(message.text.strip())
    except ValueError:
        await message.answer("❌ آیدی عددی معتبر نیست")
        return

    if not user_manager.user_exists(user_id):
        await message.answer("❌ کاربر در دیتابیس ربات پیدا نشد")
        return

    await state.update_data(points_user_id=user_id)
    await state.set_state(AdminStates.manual_points_user_amount)
    await message.answer("📝 مقدار امتیاز را بفرست (مثلا: 5 یا 2.5):")


@router.message(AdminStates.manual_points_user_amount)
async def admin_points_user_set_amount(message: Message, state: FSMContext):
    """Apply manual points to one user."""
    try:
        points = float(message.text.strip())
    except ValueError:
        await message.answer("❌ مقدار امتیاز نامعتبر است")
        return

    data = await state.get_data()
    user_id = data.get('points_user_id')
    if not user_id:
        await message.answer("❌ خطای داخلی")
        await state.clear()
        return

    user_manager.add_bonus_points(int(user_id), points)
    await message.answer(f"✅ مقدار {points} امتیاز به کاربر {user_id} اضافه شد")
    await state.clear()


@router.callback_query(F.data == "admin_points_all")
async def admin_points_all_start(callback: CallbackQuery, state: FSMContext):
    """Start global points distribution."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    await state.set_state(AdminStates.manual_points_all_amount)
    await callback.message.edit_text(
        "🌍 <b>امتیاز دستی همه کاربران</b>\n\n"
        "مقدار امتیاز را ارسال کنید تا به همه کاربران اضافه شود\n"
        "مثال: اگر 5 بزنید، به همه کاربران 5 امتیاز داده می‌شود.",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_charge")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.manual_points_all_amount)
async def admin_points_all_set_amount(message: Message, state: FSMContext):
    """Apply manual points to all users."""
    try:
        points = float(message.text.strip())
    except ValueError:
        await message.answer("❌ مقدار امتیاز نامعتبر است")
        return

    affected = user_manager.add_bonus_points_all(points)
    await message.answer(f"✅ به {affected} کاربر، {points} امتیاز اضافه شد")
    await state.clear()


@router.message(AdminStates.charge_amount)
async def set_charge_amount(message: Message, state: FSMContext):
    """Set charge amount"""
    try:
        amount = int(message.text)
        data = await state.get_data()
        user_id = data['charge_user_id']
        
        user = user_manager.get_user(user_id)
        user['balance_toman'] += amount
        user_manager.update_user(user_id, {'balance_toman': user['balance_toman']})
        
        await message.answer(f"✅ شارژ {amount:,} تومان برای کاربر {user_id} انجام شد")
        await state.clear()
    except ValueError:
        await message.answer("❌ مبلغ نامعتبر است!")


@router.callback_query(F.data == "admin_broadcast")
async def admin_broadcast(callback: CallbackQuery, state: FSMContext):
    """Broadcast message to all users"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    text = (
        f"{MessageTemplates.admin_broadcast_prompt()}\n\n"
        "می‌تونی متن HTML و <code>&lt;tg-emoji emoji-id=\"...\"&gt;🔥&lt;/tg-emoji&gt;</code> هم بفرستی."
    )
    
    await state.set_state(AdminStates.broadcast_message)
    
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="❌ انصراف", callback_data="admin_back")]
    ])
    
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_ui")
async def admin_ui(callback: CallbackQuery):
    """Admin UI customization panel."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    text = (
        "🎨 <b>ویرایش UI ربات</b>\n\n"
        "از اینجا می‌توانید متن خوش‌آمدگویی و دکمه‌های آن را تغییر دهید."
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text="📝 ویرایش متن خوش‌آمدگویی", callback_data="admin_ui_welcome_text")],
            [InlineKeyboardButton(text="🔘 ویرایش دکمه‌های خوش‌آمدگویی", callback_data="admin_ui_welcome_buttons")],
            [InlineKeyboardButton(text="🎨 انتخاب رنگ دکمه‌ها", callback_data="admin_ui_color_buttons")],
            [InlineKeyboardButton(text="📦 ویرایش قالب سفارشات", callback_data="admin_ui_order_templates")],
            [InlineKeyboardButton(text="🧠 تبدیل خودکار HTML + emoji-id", callback_data="admin_ui_extract_emoji")],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")],
        ]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_force_join")
async def admin_force_join(callback: CallbackQuery):
    """Force join configuration panel."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    cfg = ui_settings_manager.get_force_join()
    enabled = cfg.get('enabled', False)
    targets = cfg.get('targets', [])
    targets_text = "\n".join(targets) if targets else "-"
    text = (
        "📌 <b>جوین اجباری کانال/گروه</b>\n\n"
        f"وضعیت: {'✅ فعال' if enabled else '❌ غیرفعال'}\n"
        f"لیست مقصدها:\n<code>{targets_text}</code>\n\n"
        "فرمت مقصد: @channel_username یا @group_username"
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text="✏️ تنظیم لیست مقصدها", callback_data="admin_force_join_set_targets")],
            [InlineKeyboardButton(text="🔁 فعال/غیرفعال", callback_data="admin_force_join_toggle")],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_back")],
        ]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data == "admin_force_join_set_targets")
async def admin_force_join_set_targets(callback: CallbackQuery, state: FSMContext):
    """Start receiving force-join targets list."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    await state.set_state(AdminStates.force_join_targets)
    await callback.message.edit_text(
        "✏️ <b>لیست مقصدهای جوین اجباری</b>\n\n"
        "هر خط یک مورد بفرست:\n"
        "<code>@my_channel\n@my_group</code>",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_force_join")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.force_join_targets)
async def save_force_join_targets(message: Message, state: FSMContext):
    """Save force-join targets list."""
    lines = [line.strip() for line in message.text.splitlines() if line.strip()]
    targets = [line for line in lines if line.startswith('@')]
    cfg = ui_settings_manager.get_force_join()
    ui_settings_manager.set_force_join(cfg.get('enabled', False), targets)
    await message.answer(f"✅ تعداد {len(targets)} مقصد ذخیره شد")
    await state.clear()


@router.callback_query(F.data == "admin_force_join_toggle")
async def admin_force_join_toggle(callback: CallbackQuery):
    """Toggle force-join on/off."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    cfg = ui_settings_manager.get_force_join()
    new_enabled = not cfg.get('enabled', False)
    ui_settings_manager.set_force_join(new_enabled, cfg.get('targets', []))
    await callback.answer("✅ وضعیت جوین اجباری بروزرسانی شد", show_alert=False)
    await admin_force_join(callback)


@router.callback_query(F.data == "admin_dm")
async def admin_dm_start(callback: CallbackQuery, state: FSMContext):
    """Start direct-message flow by numeric user id."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    await state.set_state(AdminStates.dm_user_id)
    await callback.message.edit_text(
        "✉️ <b>ارسال پیام مدیریتی</b>\n\n"
        "آیدی عددی کاربر را ارسال کنید:",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_back")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.dm_user_id)
async def admin_dm_set_user_id(message: Message, state: FSMContext):
    """Store target user id for admin DM."""
    try:
        user_id = int(message.text.strip())
    except ValueError:
        await message.answer("❌ آیدی عددی معتبر نیست")
        return
    await state.update_data(dm_user_id=user_id)
    await state.set_state(AdminStates.dm_text)
    await message.answer("📝 حالا متن پیام را ارسال کنید:")


@router.message(AdminStates.dm_text)
async def admin_dm_send(message: Message, state: FSMContext):
    """Send admin message to selected numeric user id."""
    data = await state.get_data()
    user_id = data.get('dm_user_id')
    if not user_id:
        await message.answer("❌ خطا در دریافت آیدی کاربر")
        await state.clear()
        return
    try:
        await message.bot.send_message(user_id, f"📩 <b>پیام مدیریت:</b>\n\n{message.text}", parse_mode="HTML")
        await message.answer("✅ پیام ارسال شد")
    except Exception as exc:
        await message.answer(f"❌ ارسال ناموفق بود: {exc}")
    await state.clear()


@router.callback_query(F.data == "admin_ui_welcome_text")
async def admin_ui_welcome_text(callback: CallbackQuery, state: FSMContext):
    """Start editing welcome text."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    await state.set_state(AdminStates.ui_welcome_text)
    text = (
        "📝 <b>متن خوش‌آمدگویی جدید را ارسال کنید</b>\n\n"
        "- متن خام یا فرمت‌دار بفرستید\n"
        "- سیستم خودش تبدیل HTML انجام می‌دهد\n"
        "- emoji-id ایموجی‌های پرمیوم را استخراج می‌کند\n"
        "- برای نام کاربر از {first_name} استفاده کنید"
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_ui")]]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.message(AdminStates.ui_welcome_text)
async def save_ui_welcome_text(message: Message, state: FSMContext):
    """Save custom welcome text in JSON with auto HTML conversion."""
    converted_html = _convert_message_to_html_with_custom_emoji(message)
    emoji_ids = _extract_custom_emoji_ids(message)

    ui_settings_manager.set_welcome_text(converted_html)
    summary = (
        "✅ متن خوش‌آمدگویی ذخیره شد (تبدیل خودکار HTML انجام شد)\n\n"
        "<b>HTML نهایی:</b>\n"
        f"<code>{converted_html}</code>"
    )
    if emoji_ids:
        summary += "\n\n<b>emoji-id های استخراج‌شده:</b>\n" + "\n".join(
            [f"<code>{emoji_id}</code>" for emoji_id in emoji_ids]
        )
    else:
        summary += "\n\nℹ️ emoji-id پرمیوم پیدا نشد (ایموجی معمولی ID ندارد)."
    await message.answer(summary, parse_mode="HTML")
    await state.clear()


@router.callback_query(F.data == "admin_ui_order_templates")
async def admin_ui_order_templates(callback: CallbackQuery):
    """Menu for selecting which order template to edit."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    text = (
        "📦 <b>ویرایش قالب سفارشات</b>\n\n"
        "بخش موردنظر را انتخاب کن تا متن/ایموجی همان قسمت را ویرایش کنی."
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text="🆕 اعلان سفارش پرداختی (ادمین)", callback_data="admin_ui_tpl_admin_paid")],
            [InlineKeyboardButton(text="👛 اعلان سفارش کیف پول (ادمین)", callback_data="admin_ui_tpl_admin_wallet")],
            [InlineKeyboardButton(text="🎁 اعلان سفارش رایگان (ادمین)", callback_data="admin_ui_tpl_admin_free")],
            [InlineKeyboardButton(text="📥 اعلان رسید کاربر (ادمین)", callback_data="admin_ui_tpl_admin_receipt")],
            [InlineKeyboardButton(text="✅ پیام تکمیل سفارش (مشتری)", callback_data="admin_ui_tpl_user_completed")],
            [InlineKeyboardButton(text="📢 پیام همگانی (مشتری)", callback_data="admin_ui_tpl_user_broadcast")],
            [InlineKeyboardButton(text="👥 پیام ورود رفرال جدید", callback_data="admin_ui_tpl_user_referral_joined")],
            [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_ui")],
        ]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.callback_query(F.data.startswith("admin_ui_tpl_"))
async def admin_ui_template_pick(callback: CallbackQuery, state: FSMContext):
    """Pick specific template key and ask admin for content."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    key_map = {
        "admin_ui_tpl_admin_paid": "admin_order_paid",
        "admin_ui_tpl_admin_wallet": "admin_order_wallet",
        "admin_ui_tpl_admin_free": "admin_order_free",
        "admin_ui_tpl_admin_receipt": "admin_order_receipt",
        "admin_ui_tpl_user_completed": "user_order_completed",
        "admin_ui_tpl_user_broadcast": "user_broadcast",
        "admin_ui_tpl_user_referral_joined": "user_referral_joined",
    }
    key = key_map.get(callback.data)
    if not key:
        await callback.answer("کلید قالب نامعتبر", show_alert=True)
        return

    await state.set_state(AdminStates.ui_order_template_text)
    await state.update_data(template_key=key)

    placeholders = (
        "{order_id}, {user_id}, {full_name}, {username}, {order_type}, {currency}, "
        "{amount}, {plan_id}, {volume}, {link}, {note}, {message}, "
        "{new_user_id}, {new_username}, {points_earned}, {total_points}, {reward_coins}, {referrals_count}"
    )
    await callback.message.edit_text(
        "📝 <b>متن قالب را ارسال کنید</b>\n\n"
        f"کلید: <code>{key}</code>\n"
        f"placeholderها: <code>{placeholders}</code>\n\n"
        "می‌تونی از <code>&lt;tg-emoji emoji-id=\"...\"&gt;🔥&lt;/tg-emoji&gt;</code> هم استفاده کنی.",
        reply_markup=InlineKeyboardMarkup(
            inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_ui_order_templates")]]
        ),
        parse_mode="HTML",
    )
    await callback.answer()


@router.message(AdminStates.ui_order_template_text)
async def admin_ui_template_save(message: Message, state: FSMContext):
    """Save chosen order template with automatic html conversion."""
    data = await state.get_data()
    key = data.get('template_key')
    if not key:
        await message.answer("❌ کلید قالب پیدا نشد")
        await state.clear()
        return

    converted_html = _convert_message_to_html_with_custom_emoji(message)
    ui_settings_manager.set_text_template(key, converted_html)
    await message.answer(
        "✅ قالب ذخیره شد\n\n"
        f"کلید: <code>{key}</code>\n"
        f"<b>پیش‌نمایش HTML:</b>\n<code>{converted_html}</code>",
        parse_mode="HTML",
    )
    await state.clear()


@router.callback_query(F.data == "admin_ui_extract_emoji")
async def admin_ui_extract_emoji(callback: CallbackQuery, state: FSMContext):
    """Start HTML conversion + emoji-id extraction tool."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    await state.set_state(AdminStates.ui_extract_emoji)
    text = (
        "🧠 <b>تبدیل خودکار متن</b>\n\n"
        "متن خودت رو بفرست (با ایموجی‌ها).\n"
        "من برات:\n"
        "1) HTML نهایی می‌سازم\n"
        "2) emoji-id پرمیوم‌ها رو در میارم\n"
        "3) نمونه JSON دکمه می‌دم"
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_ui")]]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.message(AdminStates.ui_extract_emoji)
async def process_ui_extract_emoji(message: Message, state: FSMContext):
    """Convert incoming text to HTML and extract custom emoji IDs."""
    converted_html = _convert_message_to_html_with_custom_emoji(message)
    emoji_ids = _extract_custom_emoji_ids(message)

    sample_emoji_id = emoji_ids[0] if emoji_ids else "5820916017458583465"
    button_payload = [
        [
            {
                "text": "دکمه سبز",
                "callback_data": "Sourrce_kade",
                "icon_custom_emoji_id": sample_emoji_id,
                "style": "success",
            }
        ],
        [
            {
                "text": "دکمه آبی",
                "callback_data": "Sourrce_kade",
                "icon_custom_emoji_id": sample_emoji_id,
                "style": "primary",
            }
        ],
    ]

    text = (
        "✅ <b>خروجی آماده شد</b>\n\n"
        "<b>HTML:</b>\n"
        f"<code>{converted_html}</code>\n\n"
    )
    if emoji_ids:
        text += "<b>emoji-id ها:</b>\n" + "\n".join([f"<code>{i}</code>" for i in emoji_ids]) + "\n\n"
    else:
        text += "ℹ️ emoji-id پرمیوم پیدا نشد.\n\n"

    text += "<b>نمونه JSON دکمه:</b>\n"
    text += f"<code>{json.dumps(button_payload, ensure_ascii=False)}</code>"

    await message.answer(text, parse_mode="HTML")
    await state.clear()


@router.callback_query(F.data == "admin_ui_welcome_buttons")
async def admin_ui_welcome_buttons(callback: CallbackQuery, state: FSMContext):
    """Start editing welcome buttons payload."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    await state.set_state(AdminStates.ui_welcome_buttons)
    text = (
        "🔘 <b>JSON دکمه‌ها را ارسال کنید</b>\n\n"
        "ساختار نمونه:\n"
        "<code>[[{\"text\":\"a\",\"callback_data\":\"Sourrce_kade\",\"icon_custom_emoji_id\":\"5820916017458583465\",\"style\":\"success\"}]]</code>"
    )
    kb = InlineKeyboardMarkup(
        inline_keyboard=[[InlineKeyboardButton(text="❌ انصراف", callback_data="admin_ui")]]
    )
    await callback.message.edit_text(text, reply_markup=kb, parse_mode="HTML")
    await callback.answer()


@router.message(AdminStates.ui_welcome_buttons)
async def save_ui_welcome_buttons(message: Message, state: FSMContext):
    """Validate and save custom welcome buttons payload."""
    try:
        payload = json.loads(message.text)
        if not isinstance(payload, list):
            raise ValueError("root must be list")
        for row in payload:
            if not isinstance(row, list):
                raise ValueError("row must be list")
            for btn in row:
                if not isinstance(btn, dict):
                    raise ValueError("button must be object")
                if 'text' not in btn or 'callback_data' not in btn:
                    raise ValueError("button needs text and callback_data")
                if 'icon_custom_emoji_id' in btn:
                    btn['icon_custom_emoji_id'] = str(btn['icon_custom_emoji_id'])

        ui_settings_manager.set_welcome_buttons(payload)
        await message.answer("✅ دکمه‌های خوش‌آمدگویی ذخیره شد")
        await state.clear()
    except Exception:
        await message.answer("❌ JSON نامعتبر است. دوباره با ساختار صحیح ارسال کنید.")


@router.callback_query(F.data == "admin_ui_color_buttons")
async def admin_ui_color_buttons(callback: CallbackQuery):
    """Open interactive color picker for welcome buttons."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    payload = _get_welcome_buttons_or_default()
    ui_settings_manager.set_welcome_buttons(payload)

    await callback.message.edit_text(
        "🎨 <b>انتخاب رنگ دکمه‌ها</b>\n\n"
        "روی هر دکمه بزن تا رنگش را سبز/آبی/قرمز تعیین کنی.",
        reply_markup=_build_button_index_keyboard(payload),
        parse_mode="HTML",
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_ui_pick_color_"))
async def admin_ui_pick_color(callback: CallbackQuery):
    """Pick a specific button for color change."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    parts = callback.data.split("_")
    row_idx = int(parts[-2])
    col_idx = int(parts[-1])

    payload = _get_welcome_buttons_or_default()
    btn_text = payload[row_idx][col_idx].get('text', 'دکمه')

    await callback.message.edit_text(
        f"🎨 <b>انتخاب رنگ</b>\n\nدکمه انتخاب‌شده: <b>{btn_text}</b>",
        reply_markup=_build_color_picker_keyboard(row_idx, col_idx),
        parse_mode="HTML",
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_ui_set_color_"))
async def admin_ui_set_color(callback: CallbackQuery):
    """Set color style on selected button and persist JSON."""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return

    parts = callback.data.split("_")
    row_idx = int(parts[-3])
    col_idx = int(parts[-2])
    style = parts[-1]

    if style not in {"success", "primary", "danger"}:
        await callback.answer("رنگ نامعتبر", show_alert=True)
        return

    payload = _get_welcome_buttons_or_default()
    payload[row_idx][col_idx]['style'] = style
    if 'icon_custom_emoji_id' in payload[row_idx][col_idx]:
        payload[row_idx][col_idx]['icon_custom_emoji_id'] = str(payload[row_idx][col_idx]['icon_custom_emoji_id'])
    ui_settings_manager.set_welcome_buttons(payload)

    await callback.message.edit_text(
        f"✅ رنگ دکمه تغییر کرد: <code>{style}</code>",
        reply_markup=_build_button_index_keyboard(payload),
        parse_mode="HTML",
    )
    await callback.answer("رنگ ذخیره شد", show_alert=False)


@router.message(AdminStates.broadcast_message)
async def send_broadcast(message: Message, state: FSMContext):
    """Send broadcast to all users"""
    raw_input = (message.text or message.caption or "").strip()
    if not raw_input:
        await message.answer("❌ متن پیام همگانی خالی است")
        return

    converted_input = _convert_message_to_html_with_custom_emoji(message)
    default_tpl = "📢 <b>پیام از مدیریت:</b>\n\n{message}"
    template = ui_settings_manager.get_text_template('user_broadcast', default_tpl)

    all_users = user_manager.get_all_users()
    sent_count = 0
    fallback_no_premium_count = 0
    failed_count = 0
    
    for user in all_users:
        if not user.get('is_blocked', False):
            try:
                context = {
                    'message': converted_input,
                    'user_id': user.get('id', ''),
                    'full_name': user.get('first_name', '') or '',
                    'username': f"@{user.get('username')}" if user.get('username') else 'ندارد',
                }

                pretty_text = template.replace("{message}", str(context['message']))
                pretty_text = pretty_text.replace("{user_id}", html.escape(str(context['user_id'])))
                pretty_text = pretty_text.replace("{full_name}", html.escape(str(context['full_name'])))
                pretty_text = pretty_text.replace("{username}", html.escape(str(context['username'])))

                if "{message}" not in template and "{user_id}" not in template and "{full_name}" not in template and "{username}" not in template:
                    pretty_text += f"\n\n{context['message']}"

                pretty_text = _normalize_tg_emoji_html(pretty_text)

                await message.bot.send_message(
                    user['id'],
                    pretty_text,
                    parse_mode="HTML"
                )
                sent_count += 1
            except TelegramBadRequest as exc:
                try:
                    if "DOCUMENT_INVALID" in str(exc).upper():
                        await message.bot.send_message(
                            user['id'],
                            _strip_tg_emoji_tags(pretty_text),
                            parse_mode="HTML",
                        )
                        sent_count += 1
                        fallback_no_premium_count += 1
                    else:
                        failed_count += 1
                except Exception:
                    failed_count += 1
            except Exception:
                failed_count += 1
    
    await message.answer(
        "✅ ارسال پیام همگانی انجام شد\n\n"
        f"ارسال موفق: {sent_count}\n"
        f"ارسال با حذف پرمیوم (fallback): {fallback_no_premium_count}\n"
        f"ناموفق: {failed_count}"
    )
    await state.clear()


@router.callback_query(F.data == "admin_back")
async def admin_back(callback: CallbackQuery):
    """Go back to admin panel"""
    if not await is_admin(callback.from_user.id):
        await callback.answer("❌ دسترسی ندارید", show_alert=True)
        return
    
    text = """
    👑 <b>پنل مدیریت</b>
    
    خوش‌آمدید ادمین!
    """
    
    await send_or_edit_with_raw_keyboard(
        chat_id=callback.message.chat.id,
        message_id=callback.message.message_id,
        text=text,
        reply_markup=AdvancedKeyboard.admin_panel_payload(),
    )
    await callback.answer()
