from aiogram.types import InputRichMessage, RichBlockSectionHeading, RichBlockTable, RichBlockTableCell, RichTextBold
from aiogram import Router, F, Bot
from aiogram.filters import Command
from aiogram.filters.command import CommandObject
from aiogram.types import Message, CallbackQuery, ReactionTypeEmoji
from aiogram.fsm.context import FSMContext

from database import db
try:
    from config import ADMIN_IDS, STATIC_ADMIN_IDS
except ImportError:
    from config import ADMIN_IDS
    STATIC_ADMIN_IDS = list(ADMIN_IDS)
from utils.date_utils import to_shamsi
from utils.logger import get_logger
from utils import texts
from keyboards import inline, reply
from states.forms import AdminBroadcast, AdminUserSearch, AdminChangeBalance, AdminSettings, AdminReview, AdminChangeConnects, AdminSupportReply, AdminPromoCreation, DisputeChat, AdminDisputeSplit, AdminManageAdmins

logger = get_logger(__name__)
router = Router()

def admin_only(user_id: int) -> bool:
    return user_id in ADMIN_IDS

async def get_admin_main_keyboard():
    pending_verifs = len(await db.get_pending_verifications())
    pending_projs = len(await db.get_pending_projects())
    pending_withdraws = len(await db.get_pending_withdrawals())
    pending_deposits = len(await db.get_pending_deposits())
    pending_tickets = len(await db.get_open_tickets())
    return inline.admin_keyboard(
        pending_verifs=pending_verifs,
        pending_projs=pending_projs,
        pending_withdraws=pending_withdraws,
        pending_deposits=pending_deposits,
        pending_tickets=pending_tickets
    )

# ── Admin Panel Entry ──────────────────────────────────────────────────

@router.message(F.text == "⚙️ پنل ادمین")
async def admin_panel(message: Message):
    if not admin_only(message.from_user.id):
        return await message.answer("⛔️ شما دسترسی به این بخش را ندارید.")
    stats = await db.get_platform_stats()
    html_content = (
        "<h1>👑 پنل مدیریت ایکس‌لنسر</h1>"
        "<hr/>"
        "<p>به پنل مدیریت سامانه خوش آمدید. خلاصه وضعیت عملکرد سیستم در زیر آمده است:</p>"
        "<br/>"
        "<table bordered>"
        f"  <tr><th>👥 کل کاربران عضو شده</th><td>{stats['users_count']} نفر</td></tr>"
        f"  <tr><th>📌 پروژه‌های فعال</th><td>{stats['active_projects']} پروژه</td></tr>"
        f"  <tr><th>🔒 مبلغ امانی Escrow</th><td>{stats['escrow_sum']:,} تومان</td></tr>"
        f"  <tr><th>💰 درآمد کل پلتفرم</th><td>{stats['earnings']:,} تومان</td></tr>"
        "</table>"
        "<br/>"
        "<p>💡 لطفاً یکی از گزینه‌های مدیریتی زیر را جهت بررسی انتخاب کنید:</p>"
    )
    await message.bot.send_rich_message(chat_id=message.chat.id, rich_message=InputRichMessage(html=html_content), reply_markup=await get_admin_main_keyboard())

# ── Stats ──────────────────────────────────────────────────────────────

@router.callback_query(F.data == "admin_stats")
async def admin_stats(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    stats = await db.get_all_stats()
    recent_stats = await db.get_recent_activity_stats()
    
    html_content = (
        "<h1>📊 گزارش آمار و عملکرد پلتفرم ایکس‌لنسر</h1>"
        "<hr/>"
        "<h3>🔥 فعالیت ۲۴ ساعت گذشته:</h3>"
        "<table bordered striped>"
        f"  <tr><td>👥 ثبت‌نام جدید</td><td>{recent_stats['new_users_24h']} نفر</td></tr>"
        f"  <tr><td>📌 پروژه‌های ثبت‌شده</td><td>{recent_stats['new_projects_24h']} پروژه</td></tr>"
        f"  <tr><td>✅ پروژه‌های تکمیل‌شده</td><td>{recent_stats['completed_projects_24h']} پروژه</td></tr>"
        "</table>"
        "<br/>"
        "<h3>👥 آمار کلی کاربران:</h3>"
        "<table bordered striped>"
        f"  <tr><td>کل کاربران عضو شده</td><td>{stats['users']} نفر</td></tr>"
        f"  <tr><td>کارفرمایان</td><td>{stats['clients']} نفر 👔</td></tr>"
        f"  <tr><td>فریلنسرها</td><td>{stats['freelancers']} نفر 💻</td></tr>"
        f"  <tr><td>کاربران ویژه (VIP)</td><td>{stats['vip_users']} نفر ⭐</td></tr>"
        "</table>"
        "<br/>"
        "<h3>💼 وضعیت پروژه‌ها:</h3>"
        "<table bordered striped>"
        f"  <tr><td>پروژه‌های باز و فعال</td><td>{stats['open_projects']} پروژه</td></tr>"
        f"  <tr><td>پروژه‌های موفق تکمیل شده</td><td>{stats['done_projects']} پروژه</td></tr>"
        f"  <tr><td>اختلاف (شکایت)</td><td>{stats['disputed_projects']} مورد ⚖️</td></tr>"
        "</table>"
        "<br/>"
        "<h3>💰 گزارش مالی پلتفرم (تومان):</h3>"
        "<table bordered striped>"
        f"  <tr><td>مجموع درآمد کمیسیون</td><td>{stats['total_commission']:,}</td></tr>"
        f"  <tr><td>درآمد اشتراک VIP</td><td>{stats['total_vip_revenue']:,}</td></tr>"
        f"  <tr><td>امانی در صندوق Escrow</td><td>{stats['total_escrow_held']:,}</td></tr>"
        f"  <tr><td>کل تسویه‌حساب‌های پرداختی</td><td>{stats['total_withdrawn']:,}</td></tr>"
        "</table>"
    )
    rich_msg = InputRichMessage(html=html_content)
    
    await callback.message.edit_text(text=None, reply_markup=await get_admin_main_keyboard(), rich_message=rich_msg)
    await callback.answer()

# ── Users List ─────────────────────────────────────────────────────────

@router.callback_query(F.data == "admin_users")
async def admin_users(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    limit = 10
    offset = 0
    users = await db.get_all_users_paginated(limit=limit, offset=offset)
    total = await db.count_all_users()
    
    text = f"👥 <b>لیست کاربران پلتفرم ایکس‌لنسر (تعداد کل: {total} نفر):</b>\n\nبرای مدیریت هر کاربر روی دکمه آن کلیک کنید:"
    markup = inline.admin_users_pagination_keyboard(users, offset=offset, total=total, limit=limit)
    await callback.message.edit_text(text=None, reply_markup=markup, rich_message=InputRichMessage(html=text))
    await callback.answer()

@router.callback_query(F.data.startswith("admin_users_page_"))
async def admin_users_page(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    offset = int(callback.data.split("_")[-1])
    limit = 10
    users = await db.get_all_users_paginated(limit=limit, offset=offset)
    total = await db.count_all_users()
    
    text = f"👥 <b>لیست کاربران پلتفرم ایکس‌لنسر (تعداد کل: {total} نفر):</b>\n\nبرای مدیریت هر کاربر روی دکمه آن کلیک کنید:"
    markup = inline.admin_users_pagination_keyboard(users, offset=offset, total=total, limit=limit)
    await callback.message.edit_text(text=None, reply_markup=markup, rich_message=InputRichMessage(html=text))
    await callback.answer()

# ── Broadcast ──────────────────────────────────────────────────────────

@router.callback_query(F.data == "admin_broadcast")
async def admin_broadcast_start(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    await state.set_state(AdminBroadcast.waiting_for_message)
    await callback.message.answer("📢 پیام خود را برای ارسال همگانی بنویسید:\n_(ارسال به همه کاربران)_", parse_mode="HTML")
    await callback.answer()

@router.message(AdminBroadcast.waiting_for_message)
async def admin_broadcast_send(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        return
    await state.clear()
    try: await message.react([ReactionTypeEmoji(emoji="📢")])
    except: pass
    users = await db.get_all_users(limit=100000)
    user_ids = [u['user_id'] for u in users]
    
    from utils.broadcaster import safe_broadcast
    import asyncio
    
    await message.answer(f"⏳ <b>عملیات ارسال همگانی آغاز شد...</b>\n\nتعداد مخاطبین: {len(user_ids)} نفر\nلطفاً صبور باشید. پس از پایان ارسال، گزارش آن برای شما ارسال خواهد شد.", parse_mode="HTML")
    
    is_rich = False
    rich_tags = ["<table", "<h1>", "<h2>", "<h3>", "<h4>", "<h5>", "<h6>", "<hr", "<details>"]
    text_lower = message.text.lower()
    if any(tag in text_lower for tag in rich_tags):
        is_rich = True
        
    if is_rich:
        rich_msg = InputRichMessage(html=message.text)
        asyncio.create_task(
            safe_broadcast(
                bot=bot,
                user_ids=user_ids,
                report_admin_id=message.from_user.id,
                rich_message=rich_msg
            )
        )
    else:
        asyncio.create_task(
            safe_broadcast(
                bot=bot,
                user_ids=user_ids,
                text=f"📢 <b>اطلاعیه از ایکس‌لنسر:</b>\n\n{message.text}",
                report_admin_id=message.from_user.id
            )
        )
@router.message(Command("addbalance"))
async def add_balance_cmd(message: Message):
    """Usage: /addbalance user_id amount"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 3 or not parts[1].isdigit() or not parts[2].lstrip('-').isdigit():
        return await message.answer("استفاده: /addbalance user_id amount")
    uid = int(parts[1])
    amount = int(parts[2])
    await db.update_balance(uid, amount, "manual", f"افزایش دستی توسط ادمین")
    await message.answer(f"✅ {amount:,} تومان به کاربر {uid} اضافه شد.")

@router.message(Command("refund"))
async def admin_refund_cmd(message: Message, bot: Bot, state: FSMContext):
    """Usage: /refund project_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /refund project_id")
    
    project_id = int(parts[1])
    project = await db.get_project(project_id)
    if not project:
        return await message.answer("❌ پروژه یافت نشد.")
    
    import aiosqlite
    from config import DB_PATH
    amount = 0
    freelancer_id = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT amount, freelancer_id FROM escrow WHERE project_id = ? AND status = "held"', (project_id,)) as cursor:
                row = await cursor.fetchone()
                if row:
                    amount = row['amount']
                    freelancer_id = row['freelancer_id']
    except Exception as e:
        return await message.answer(f"❌ خطا در خواندن اطلاعات پرداخت امن: {e}")

    success = await db.refund_project(project_id)
    if not success:
        return await message.answer("❌ خطا در استرداد وجه. ممکن است پروژه در جریان نباشد یا قبلاً تسویه شده باشد.")
    
    await message.answer(f"✅ وجه پروژه #{project_id} به مبلغ {amount:,} تومان با موفقیت به کارفرما استرداد یافت.")
    await clear_dispute_chat_states(bot, state.storage, project_id, project['client_id'], freelancer_id)
    
    # Send PDF Refund Receipt to both parties
    try:
        client_user = await db.get_user(project['client_id'])
        freelancer_user = await db.get_user(freelancer_id) if freelancer_id else None
        cl_name = (client_user['full_name'] or client_user['username'] or str(project['client_id'])) if client_user else str(project['client_id'])
        fl_name = (freelancer_user['full_name'] or freelancer_user['username'] or str(freelancer_id)) if freelancer_user else str(freelancer_id or 0)
        
        from handlers.common import send_invoice_to_parties
        await send_invoice_to_parties(
            bot=bot,
            project_id=project_id,
            project_title=project['title'],
            client_id=project['client_id'],
            client_name=cl_name,
            freelancer_id=freelancer_id or 0,
            freelancer_name=fl_name,
            amount=amount,
            commission=0,
            payout=0,
            commission_pct=0,
            is_refund=True,
        )
    except Exception as e:
        print(f"Error sending refund invoice in admin_refund_cmd: {e}")
        
    # Notify client and freelancer
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        
        # client keyboard
        cl_builder = InlineKeyboardBuilder()
        cl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back")
        await bot.send_message(
            project['client_id'],
            f"⚖️ <b>رأی داوری: لغو و استرداد پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project['title']}</b>\n"
            f"💰 مبلغ بازگشتی: <b>{amount:,} تومان</b>\n"
            f"\n"
            f"با رأی داور حل اختلاف، پروژه لغو شده و هزینه به کیف پول شما بازگردانده شد.",
            reply_markup=cl_builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
        
        if freelancer_id:
            fl_builder = InlineKeyboardBuilder()
            fl_builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
            await bot.send_message(
                freelancer_id,
                f"⚖️ <b>رأی داوری: لغو و استرداد پروژه</b>\n"
                f"\n"
                f"📌 پروژه: <b>{project['title']}</b>\n"
                f"\n"
                f"با رأی داور حل اختلاف، پروژه لغو شده و وجه آن به کارفرما مسترد گردید. جهت پیگیری روی دکمه زیر کلیک کنید:",
                reply_markup=fl_builder.as_markup(),
                parse_mode="HTML"
            )
    except Exception:
        pass


@router.message(Command("releaseescrow"))
async def admin_release_escrow_cmd(message: Message, bot: Bot, state: FSMContext):
    """Usage: /releaseescrow project_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /releaseescrow project_id")
    
    project_id = int(parts[1])
    project = await db.get_project(project_id)
    if not project:
        return await message.answer("❌ پروژه یافت نشد.")
    
    import aiosqlite
    from config import DB_PATH
    amount = 0
    freelancer_id = None
    client_id = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT amount, freelancer_id, client_id FROM escrow WHERE project_id = ? AND status = "held"', (project_id,)) as cursor:
                row = await cursor.fetchone()
                if row:
                    amount = row['amount']
                    freelancer_id = row['freelancer_id']
                    client_id = row['client_id']
    except Exception as e:
        return await message.answer(f"❌ خطا در خواندن اطلاعات پرداخت امن: {e}")

    if not freelancer_id or not client_id or amount <= 0:
        return await message.answer("❌ تراکنش پرداخت امن معتبری برای این پروژه یافت نشد (یا قبلاً آزاد/مسترد شده است).")
    
    commission_rate = await db.get_user_commission_rate(freelancer_id)
    commission_pct = int(commission_rate * 100)
    commission = int(amount * commission_rate)
    payout = amount - commission

    try:
        await db.complete_project(
            project_id=project_id,
            freelancer_id=freelancer_id,
            amount=amount,
            commission_rate=commission_rate,
            client_id=client_id,
        )
    except Exception as e:
        return await message.answer(f"❌ خطا در آزادسازی وجه: {e}")

    await message.answer(
        f"✅ وجه پروژه #{project_id} به مبلغ {amount:,} تومان با موفقیت به فریلنسر آزاد شد.\n"
        f"سهم فریلنسر: {payout:,} تومان | کمیسیون پلتفرم ({commission_pct}%): {commission:,} تومان"
    )
    await clear_dispute_chat_states(bot, state.storage, project_id, client_id, freelancer_id)
    
    # Send PDF Invoice to both parties
    try:
        client_user = await db.get_user(client_id)
        freelancer_user = await db.get_user(freelancer_id)
        cl_name = (client_user['full_name'] or client_user['username'] or str(client_id)) if client_user else str(client_id)
        fl_name = (freelancer_user['full_name'] or freelancer_user['username'] or str(freelancer_id)) if freelancer_user else str(freelancer_id)
        
        from handlers.common import send_invoice_to_parties
        await send_invoice_to_parties(
            bot=bot,
            project_id=project_id,
            project_title=project['title'] if project else f"#{project_id}",
            client_id=client_id,
            client_name=cl_name,
            freelancer_id=freelancer_id,
            freelancer_name=fl_name,
            amount=amount,
            commission=commission,
            payout=payout,
            commission_pct=commission_pct,
            is_refund=False,
        )
    except Exception as e:
        print(f"Error sending escrow release invoice in admin_release_escrow_cmd: {e}")
        
    # Notify client and freelancer
    project_title = project['title'] if project else f"#{project_id}"
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        
        # client keyboard
        cl_builder = InlineKeyboardBuilder()
        cl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back")
        await bot.send_message(
            client_id,
            f"⚖️ <b>رأی داوری: تکمیل و آزادسازی پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project_title}</b>\n"
            f"💰 مبلغ پرداختی: <b>{amount:,} تومان</b>\n"
            f"\n"
            f"پس از بررسی داور حل اختلاف، وجه امانی پروژه به نفع فریلنسر آزاد و پروژه خاتمه یافت.",
            reply_markup=cl_builder.as_markup(),
            parse_mode="HTML"
        )
        
        # freelancer keyboard
        fl_builder = InlineKeyboardBuilder()
        fl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back_freelancer")
        await bot.send_message(
            freelancer_id,
            f"⚖️ <b>رأی داوری: تکمیل و آزادسازی پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project_title}</b>\n"
            f"💰 مبلغ واریزی: <b>{payout:,} تومان</b>\n"
            f"\n"
            f"با رأی داور حل اختلاف، پروژه تایید نهایی گردید و سهم شما به کیف پولتان واریز شد.",
            reply_markup=fl_builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
    except Exception:
        pass


# ── Admin Withdrawal/Payout Approvals ───────────────────────────────────

@router.message(Command("approvewithdraw"))
async def admin_approve_withdraw_cmd(message: Message, bot: Bot):
    """Usage: /approvewithdraw withdrawal_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /approvewithdraw withdrawal_id")
    
    wid = int(parts[1])
    w = await db.get_withdrawal(wid)
    if not w:
        return await message.answer("❌ درخواست برداشت یافت نشد.")
    if w['status'] != 'pending':
        return await message.answer("❌ این درخواست قبلاً تعیین تکلیف شده است.")
        
    success = await db.approve_withdrawal_request(wid)
    if not success:
        return await message.answer("❌ خطا در تایید درخواست.")
        
    await message.answer(f"✅ درخواست تسویه #{wid} به مبلغ {w['amount']:,} تومان تایید شد.")
    
    # Notify user
    try:
        user = await db.get_user(w['user_id'])
        role_back = "wallet_menu_back_freelancer" if user and user.get('role') == 'freelancer' else "wallet_menu_back"
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💰 مشاهده کیف پول", callback_data=role_back)
        
        await bot.send_message(
            w['user_id'],
            f"✅ <b>تسویه حساب با موفقیت انجام شد</b>\n"
            f"\n"
            f"🆔 شماره درخواست: `#{wid}`\n"
            f"💰 مبلغ واریزی: <b>{w['amount']:,} تومان</b>\n"
            f"\n"
            f"مبلغ مورد نظر با موفقیت پرداخت گردید. برای مشاهده وضعیت کیف پول خود دکمه زیر را بزنید:",
            reply_markup=builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
    except:
        pass

@router.message(Command("rejectwithdraw"))
async def admin_reject_withdraw_cmd(message: Message, bot: Bot):
    """Usage: /rejectwithdraw withdrawal_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /rejectwithdraw withdrawal_id")
    
    wid = int(parts[1])
    w = await db.get_withdrawal(wid)
    if not w:
        return await message.answer("❌ درخواست برداشت یافت نشد.")
    if w['status'] != 'pending':
        return await message.answer("❌ این درخواست قبلاً تعیین تکلیف شده است.")
        
    success = await db.reject_withdrawal_request(wid)
    if not success:
        return await message.answer("❌ خطا در رد درخواست.")
        
    await message.answer(f"❌ درخواست تسویه #{wid} به مبلغ {w['amount']:,} تومان رد شد و وجه به کیف پول کاربر بازگردانده شد.")
    
    # Notify user
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
        
        await bot.send_message(
            w['user_id'],
            f"❌ <b>رد درخواست تسویه حساب</b>\n"
            f"\n"
            f"🆔 شماره درخواست: `#{wid}`\n"
            f"💵 مبلغ: <b>{w['amount']:,} تومان</b>\n"
            f"\n"
            f"درخواست تسویه حساب شما رد گردید و مبلغ فوق تماماً به کیف پول شما مسترد شد. جهت پیگیری دکمه زیر را کلیک کنید:",
            reply_markup=builder.as_markup(),
            parse_mode="HTML"
        )
    except:
        pass

@router.callback_query(F.data.startswith("admin_withdraw_approve_"))
async def callback_admin_approve_withdraw(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    wid = int(callback.data.split("_")[-1])
    w = await db.get_withdrawal(wid)
    if not w:
        return await callback.answer("درخواست یافت نشد.", show_alert=True)
    if w['status'] != 'pending':
        return await callback.answer("این درخواست قبلاً تعیین تکلیف شده است.", show_alert=True)
        
    success = await db.approve_withdrawal_request(wid)
    if not success:
        return await callback.answer("خطا در تایید درخواست.", show_alert=True)
        
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_withdrawals")
    html_msg = (
        "<h1>💸 درخواست تسویه حساب</h1>"
        "<hr/>"
        "<h3>✅ درخواست تسویه با موفقیت تایید و پرداخت گردید.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ تایید شد!")
    
    # Notify user
    try:
        user = await db.get_user(w['user_id'])
        role_back = "wallet_menu_back_freelancer" if user and user.get('role') == 'freelancer' else "wallet_menu_back"
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💰 مشاهده کیف پول", callback_data=role_back)
        
        html_msg = (
            f"<h1>✅ تسویه حساب با موفقیت انجام شد</h1>"
            "<hr/>"
            f"<p>درخواست تسویه حساب شما تایید گردید و مبلغ مورد نظر به حساب بانکی شما واریز شد.</p>"
            "<br/>"
            "<table bordered>"
            f"  <tr><th>🆔 شماره درخواست</th><td>#{wid}</td></tr>"
            f"  <tr><th>💰 مبلغ واریز شده</th><td>{w['amount']:,} تومان</td></tr>"
            "</table>"
        )
        await bot.send_rich_message(
            chat_id=w['user_id'],
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup(),
            message_effect_id="5046509860389126442"
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about withdrawal approval: {e}")

@router.callback_query(F.data.startswith("admin_withdraw_reject_"))
async def callback_admin_reject_withdraw(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    wid = int(callback.data.split("_")[-1])
    w = await db.get_withdrawal(wid)
    if not w:
        return await callback.answer("درخواست یافت نشد.", show_alert=True)
    if w['status'] != 'pending':
        return await callback.answer("این درخواست قبلاً تعیین تکلیف شده است.", show_alert=True)
        
    success = await db.reject_withdrawal_request(wid)
    if not success:
        return await callback.answer("خطا در رد درخواست.", show_alert=True)
        
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_withdrawals")
    html_msg = (
        "<h1>💸 درخواست تسویه حساب</h1>"
        "<hr/>"
        "<h3>❌ درخواست تسویه توسط ادمین رد و کل مبلغ به کیف پول کاربر بازگردانده شد.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("❌ رد شد!")
    
    # Notify user
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
        
        html_msg = (
            f"<h1>❌ رد درخواست تسویه حساب</h1>"
            "<hr/>"
            f"<p>درخواست تسویه حساب شما متاسفانه رد گردید و مبلغ فوق تماماً به موجودی کیف پول شما بازگردانده شد.</p>"
            "<br/>"
            "<table bordered>"
            f"  <tr><th>🆔 شماره درخواست</th><td>#{wid}</td></tr>"
            f"  <tr><th>💵 مبلغ مسترد شده</th><td>{w['amount']:,} تومان</td></tr>"
            "</table>"
            "<br/>"
            "<p>در صورت بروز هرگونه مشکل یا اعتراض، با کلیک بر روی دکمه زیر تیکت پشتیبانی ثبت کنید.</p>"
        )
        await bot.send_rich_message(
            chat_id=w['user_id'],
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup()
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about withdrawal rejection: {e}")

@router.message(Command("ban"))
async def ban_user_cmd(message: Message):
    """Usage: /ban user_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /ban user_id")
    uid = int(parts[1])
    
    user = await db.get_user(uid)
    if not user:
        return await message.answer("❌ کاربر یافت نشد.")
        
    await db.ban_user(uid)
    name = user['full_name'] or user['username'] or str(uid)
    await message.answer(f"✅ کاربر {uid} ({name}) با موفقیت مسدود شد.")


@router.message(Command("unban"))
async def unban_user_cmd(message: Message):
    """Usage: /unban user_id"""
    if not admin_only(message.from_user.id):
        return
    parts = message.text.split()
    if len(parts) != 2 or not parts[1].isdigit():
        return await message.answer("استفاده: /unban user_id")
    uid = int(parts[1])
    
    user = await db.get_user(uid)
    if not user:
        return await message.answer("❌ کاربر یافت نشد.")
        
    await db.unban_user(uid)
    name = user['full_name'] or user['username'] or str(uid)
    await message.answer(f"✅ کاربر {uid} ({name}) با موفقیت فعال (آن‌بن) شد.")


# ── Admin Panel Navigation & Escrow/Withdrawal Lists ───────────────────

@router.callback_query(F.data == "admin_back_to_panel")
async def back_to_panel(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    stats = await db.get_platform_stats()
    html_content = (
        "<h1>👑 پنل مدیریت ایکس‌لنسر</h1>"
        "<hr/>"
        "<p>به پنل مدیریت سامانه خوش آمدید. خلاصه وضعیت عملکرد سیستم در زیر آمده است:</p>"
        "<br/>"
        "<table bordered>"
        f"  <tr><th>👥 کل کاربران عضو شده</th><td>{stats['users_count']} نفر</td></tr>"
        f"  <tr><th>📌 پروژه‌های فعال</th><td>{stats['active_projects']} پروژه</td></tr>"
        f"  <tr><th>🔒 مبلغ امانی Escrow</th><td>{stats['escrow_sum']:,} تومان</td></tr>"
        f"  <tr><th>💰 درآمد کل پلتفرم</th><td>{stats['earnings']:,} تومان</td></tr>"
        "</table>"
        "<br/>"
        "<p>💡 لطفاً یکی از گزینه‌های مدیریتی زیر را جهت بررسی انتخاب کنید:</p>"
    )
    await callback.message.edit_text(text=None, reply_markup=await get_admin_main_keyboard(), rich_message=InputRichMessage(html=html_content))
    await callback.answer()


@router.callback_query(F.data == "admin_escrows")
async def admin_escrows_list(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    escrows = await db.get_active_escrows()
    if not escrows:
        await callback.message.edit_text(
            text=None,
            reply_markup=await get_admin_main_keyboard(),
            rich_message=InputRichMessage(html="⚖️ <b>هیچ پرداخت امن فعالی وجود ندارد.</b>")
        )
        await callback.answer()
        return
    
    text = "⚖️ <b>لیست پرداخت‌های امن فعال (پروژه‌های در حال انجام):</b>\n\n"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for e in escrows:
        builder.button(
            text=f"پروژه #{e['project_id']} — {e['amount']:,}₸",
            callback_data=f"admin_view_escrow_{e['project_id']}"
        )
    builder.button(text="🔙 بازگشت", callback_data="admin_back_to_panel")
    builder.adjust(1)
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_view_escrow_"))
async def admin_view_escrow(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    import aiosqlite
    from config import DB_PATH
    escrow = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT * FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
                escrow = await cursor.fetchone()
    except Exception as e:
        return await callback.message.answer(f"خطا در خواندن اطلاعات پرداخت امن: {e}")
        
    if not escrow:
        return await callback.answer("پرداخت امن فعال برای این پروژه یافت نشد.", show_alert=True)
        
    client = await db.get_user(escrow['client_id'])
    freelancer = await db.get_user(escrow['freelancer_id'])
    
    client_name = client['full_name'] or client['username'] or str(escrow['client_id']) if client else "نامشخص"
    freelancer_name = freelancer['full_name'] or freelancer['username'] or str(escrow['freelancer_id']) if freelancer else "نامشخص"
    
    html_content = (
        f"<h1>⚖️ جزئیات پرداخت امن پروژه #{pid}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>📌 پروژه</th><td>{project['title']}</td></tr>"
        f"  <tr><th>👔 کارفرما</th><td>{client_name} (ID: <code>{escrow['client_id']}</code>)</td></tr>"
        f"  <tr><th>💻 فریلنسر</th><td>{freelancer_name} (ID: <code>{escrow['freelancer_id']}</code>)</td></tr>"
        f"  <tr><th>💰 مبلغ بلوکه شده</th><td>{escrow['amount']:,} تومان</td></tr>"
        f"  <tr><th>📅 تاریخ ایجاد</th><td>{to_shamsi(escrow['created_at'])}</td></tr>"
        "</table>"
    )
    rich_msg = InputRichMessage(html=html_content)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🗳 داوری و تسویه اختلاف", callback_data=f"admin_dispute_settle_menu_{pid}", style="success")
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_escrows", style="primary")
    builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=rich_msg)
    await callback.answer()

async def notify_dispute_resolution(bot: Bot, project, freelancer_amount: int, client_amount: int):
    # Notify Client
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back")
        await bot.send_message(
            project['client_id'],
            f"⚖️ <b>رأی داوری: تسویه و تقسیم سهم پروژه</b>\n\n"
            f"📌 پروژه: <b>{project['title']}</b>\n"
            f"💰 سهم بازگشتی به شما: <b>{client_amount:,} تومان</b>\n\n"
            f"بر اساس رأی داور حل اختلاف، وجه امانی پروژه تقسیم گردید و سهم شما به کیف پولتان بازگردانده شد.",
            reply_markup=builder.as_markup(),
            parse_mode="HTML"
        )
    except Exception:
        pass
        
    # Notify Freelancer
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back_freelancer")
        
        # Calculate payout
        freelancer_id = project['chosen_freelancer_id']
        commission_rate = await db.get_user_commission_rate(freelancer_id)
        commission = int(freelancer_amount * commission_rate)
        payout = freelancer_amount - commission
        
        await bot.send_message(
            freelancer_id,
            f"⚖️ <b>رأی داوری: تسویه و تقسیم سهم پروژه</b>\n\n"
            f"📌 پروژه: <b>{project['title']}</b>\n"
            f"💰 سهم واریزی به شما: <b>{payout:,} تومان</b> (کمیسیون: {commission:,} تومان)\n\n"
            f"با رأی داور حل اختلاف، پروژه تسویه شد و سهم کار شما به کیف پولتان واریز گردید.",
            reply_markup=builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
    except Exception:
        pass

    # Send PDF Dispute Split Invoice to both parties
    try:
        freelancer_id = project['chosen_freelancer_id']
        commission_rate = await db.get_user_commission_rate(freelancer_id) if freelancer_id else 0.10
        commission = int(freelancer_amount * commission_rate)
        payout = freelancer_amount - commission
        
        client_user = await db.get_user(project['client_id'])
        freelancer_user = await db.get_user(freelancer_id) if freelancer_id else None
        cl_name = (client_user['full_name'] or client_user['username'] or str(project['client_id'])) if client_user else str(project['client_id'])
        fl_name = (freelancer_user['full_name'] or freelancer_user['username'] or str(freelancer_id)) if freelancer_user else str(freelancer_id or 0)
        
        from handlers.common import send_invoice_to_parties
        await send_invoice_to_parties(
            bot=bot,
            project_id=project['project_id'],
            project_title=project['title'],
            client_id=project['client_id'],
            client_name=cl_name,
            freelancer_id=freelancer_id or 0,
            freelancer_name=fl_name,
            amount=freelancer_amount + client_amount,
            commission=commission,
            payout=payout,
            commission_pct=int(commission_rate * 100),
            is_refund=(freelancer_amount == 0),
        )
    except Exception as e:
        print(f"Error sending dispute resolution invoice: {e}")


@router.callback_query(F.data.startswith("admin_dispute_settle_menu_"))
async def admin_dispute_settle_menu(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    
    import aiosqlite
    from config import DB_PATH
    escrow = None
    async with aiosqlite.connect(DB_PATH) as conn:
        conn.row_factory = aiosqlite.Row
        async with conn.execute('SELECT amount FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
            escrow = await cursor.fetchone()
            
    if not escrow:
        return await callback.answer("پرداخت امن فعالی یافت نشد.", show_alert=True)
        
    amount = escrow['amount']
    from keyboards import inline
    html_msg = (
        f"<h1>⚖️ داوری اختلاف پروژه #{pid}</h1>"
        "<hr/>"
        f"<p>💰 مبلغ کل در صندوق امانی: <b>{amount:,} تومان</b></p>"
        f"<br/>"
        f"<p>لطفاً نحوه تقسیم وجه و تسویه پروژه را انتخاب کنید:</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_dispute_split_keyboard(pid),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_dispute_split_50_50_"))
async def admin_dispute_split_50_50(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    import aiosqlite
    from config import DB_PATH
    escrow = None
    async with aiosqlite.connect(DB_PATH) as conn:
        conn.row_factory = aiosqlite.Row
        async with conn.execute('SELECT amount FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
            escrow = await cursor.fetchone()
            
    if not escrow:
        return await callback.answer("پرداخت امن فعالی یافت نشد.", show_alert=True)
        
    amount = escrow['amount']
    freelancer_amount = amount // 2
    client_amount = amount - freelancer_amount
    
    success = await db.resolve_dispute_split(pid, freelancer_amount, client_amount)
    if not success:
        return await callback.answer("خطا در تقسیم وجه.", show_alert=True)
        
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست شکایات", callback_data="admin_disputes")
    
    html_msg = (
        f"<h1>⚖️ تسویه داوری پروژه #{pid}</h1>"
        "<hr/>"
        f"<h3>✅ تسویه با تقسیم سهم ۵۰/۵۰ با موفقیت انجام شد.</h3>"
        f"<br/>"
        f"<table bordered>"
        f"  <tr><th>💰 کل مبلغ صندوق</th><td>{amount:,} تومان</td></tr>"
        f"  <tr><th>💻 سهم فریلنسر (ناخالص)</th><td>{freelancer_amount:,} تومان</td></tr>"
        f"  <tr><th>👔 سهم کارفرما</th><td>{client_amount:,} تومان</td></tr>"
        f"</table>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ ثبت شد!")
    await notify_dispute_resolution(bot, project, freelancer_amount, client_amount)


@router.callback_query(F.data.startswith("admin_dispute_split_custom_"))
async def admin_dispute_split_custom(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    
    import aiosqlite
    from config import DB_PATH
    escrow = None
    async with aiosqlite.connect(DB_PATH) as conn:
        conn.row_factory = aiosqlite.Row
        async with conn.execute('SELECT amount FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
            escrow = await cursor.fetchone()
            
    if not escrow:
        return await callback.answer("پرداخت امن فعالی یافت نشد.", show_alert=True)
        
    amount = escrow['amount']
    await state.update_data(dispute_project_id=pid, dispute_total_amount=amount)
    await state.set_state(AdminDisputeSplit.waiting_for_freelancer_amount)
    
    await callback.message.answer(
        f"✍️ <b>تقسیم دستی سهم داوری پروژه #{pid}</b>\n\n"
        f"💰 کل مبلغ صندوق: <b>{amount:,} تومان</b>\n\n"
        f"لطفاً سهم فریلنسر را به <b>تومان</b> وارد کنید (فقط عدد انگلیسی، مثلاً `120000`):\n"
        f"مابقی کل مبلغ به صورت خودکار به کارفرما مسترد خواهد شد.",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()


@router.message(AdminDisputeSplit.waiting_for_freelancer_amount)
async def process_admin_dispute_split_custom(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
        
    if message.text == texts.BTN_BACK:
        await state.clear()
        return await message.answer("لغو شد.", reply_markup=reply.client_main_menu(is_admin=True))
        
    data = await state.get_data()
    pid = data.get("dispute_project_id")
    total_amount = data.get("dispute_total_amount")
    
    val_str = message.text.strip()
    if not val_str.isdigit():
        return await message.answer("⚠️ لطفاً یک عدد صحیح معتبر (به تومان) وارد کنید:")
        
    freelancer_amount = int(val_str)
    if freelancer_amount < 0 or freelancer_amount > total_amount:
        return await message.answer(f"⚠️ سهم فریلنسر نمی‌تواند کمتر از صفر یا بیشتر از کل موجودی صندوق (<b>{total_amount:,} تومان</b>) باشد. مجدداً وارد کنید:", parse_mode="HTML")
        
    client_amount = total_amount - freelancer_amount
    await state.clear()
    
    project = await db.get_project(pid)
    if not project:
        return await message.answer("❌ پروژه یافت نشد.")
        
    success = await db.resolve_dispute_split(pid, freelancer_amount, client_amount)
    if not success:
        return await message.answer("❌ خطا در ثبت اطلاعات تقسیم وجه داوری.")
        
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست شکایات", callback_data="admin_disputes")
    
    await message.answer(
        f"✅ <b>تقسیم دستی وجه با موفقیت انجام و مبالغ واریز شدند.</b>\n\n"
        f"💰 مبلغ کل صندوق: <b>{total_amount:,} تومان</b>\n"
        f"💻 سهم فریلنسر (ناخالص): <b>{freelancer_amount:,} تومان</b>\n"
        f"👔 سهم کارفرما (استرداد): <b>{client_amount:,} تومان</b>",
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )
    
    await notify_dispute_resolution(bot, project, freelancer_amount, client_amount)


@router.callback_query(F.data.startswith("admin_escrow_release_"))
async def callback_admin_escrow_release(callback: CallbackQuery, bot: Bot, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    import aiosqlite
    from config import DB_PATH
    amount = 0
    freelancer_id = None
    client_id = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT amount, freelancer_id, client_id FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
                row = await cursor.fetchone()
                if row:
                    amount = row['amount']
                    freelancer_id = row['freelancer_id']
                    client_id = row['client_id']
    except Exception as e:
        return await callback.answer(f"خطا در خواندن پرداخت امن: {e}", show_alert=True)

    if not freelancer_id or not client_id or amount <= 0:
        return await callback.answer("تراکنش پرداخت امن معتبری یافت نشد.", show_alert=True)

    commission_rate = await db.get_user_commission_rate(freelancer_id)
    commission_pct = int(commission_rate * 100)
    commission = int(amount * commission_rate)
    payout = amount - commission

    try:
        await db.complete_project(
            project_id=pid,
            freelancer_id=freelancer_id,
            amount=amount,
            commission_rate=commission_rate,
            client_id=client_id,
        )
    except Exception as e:
        return await callback.answer(f"خطا در تکمیل پروژه: {e}", show_alert=True)

    html_msg = (
        f"<h1>⚖️ داوری اختلاف پروژه #{pid}</h1>"
        "<hr/>"
        f"<h3>✅ پرونده توسط ادمین آزاد شد.</h3>"
        f"<p>مبلغ <b>{payout:,} تومان</b> به فریلنسر منتقل گردید.</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=None,
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ وجه آزاد شد!")
    await clear_dispute_chat_states(bot, state.storage, pid, client_id, freelancer_id)

    # Send PDF Invoice to both parties
    client_user = await db.get_user(client_id)
    freelancer_user = await db.get_user(freelancer_id)
    cl_name = (client_user['full_name'] or client_user['username'] or str(client_id)) if client_user else str(client_id)
    fl_name = (freelancer_user['full_name'] or freelancer_user['username'] or str(freelancer_id)) if freelancer_user else str(freelancer_id)
    
    from handlers.common import send_invoice_to_parties
    await send_invoice_to_parties(
        bot=bot,
        project_id=pid,
        project_title=project['title'],
        client_id=client_id,
        client_name=cl_name,
        freelancer_id=freelancer_id,
        freelancer_name=fl_name,
        amount=amount,
        commission=commission,
        payout=payout,
        commission_pct=commission_pct,
        is_refund=False,
    )

    # Notify parties
    project_title = project['title'] if project else f"#{pid}"
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        
        # client keyboard
        cl_builder = InlineKeyboardBuilder()
        cl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back")
        await bot.send_message(
            client_id,
            f"⚖️ <b>رأی داوری: تکمیل و آزادسازی پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project_title}</b>\n"
            f"💰 مبلغ پرداختی: <b>{amount:,} تومان</b>\n"
            f"\n"
            f"پس از بررسی داور حل اختلاف، وجه امانی پروژه به نفع فریلنسر آزاد و پروژه خاتمه یافت.",
            reply_markup=cl_builder.as_markup(),
            parse_mode="HTML"
        )
        
        # freelancer keyboard
        fl_builder = InlineKeyboardBuilder()
        fl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back_freelancer")
        await bot.send_message(
            freelancer_id,
            f"⚖️ <b>رأی داوری: تکمیل و آزادسازی پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project_title}</b>\n"
            f"💰 مبلغ واریزی: <b>{payout:,} تومان</b>\n"
            f"\n"
            f"با رأی داور حل اختلاف، پروژه تایید نهایی گردید و سهم شما به کیف پولتان واریز شد.",
            reply_markup=fl_builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
    except:
        pass


@router.callback_query(F.data.startswith("admin_escrow_refund_"))
async def callback_admin_escrow_refund(callback: CallbackQuery, bot: Bot, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    import aiosqlite
    from config import DB_PATH
    amount = 0
    freelancer_id = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT amount, freelancer_id FROM escrow WHERE project_id = ? AND status = "held"', (pid,)) as cursor:
                row = await cursor.fetchone()
                if row:
                    amount = row['amount']
                    freelancer_id = row['freelancer_id']
    except Exception as e:
        return await callback.answer(f"خطا در خواندن پرداخت امن: {e}", show_alert=True)

    success = await db.refund_project(pid)
    if not success:
        return await callback.answer("خطا در استرداد وجه پروژه.", show_alert=True)

    html_msg = (
        f"<h1>⚖️ داوری اختلاف پروژه #{pid}</h1>"
        "<hr/>"
        f"<h3>❌ پرونده توسط ادمین لغو و وجه مسترد شد.</h3>"
        f"<p>مبلغ <b>{amount:,} تومان</b> به کارفرما بازگردانده شد.</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=None,
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("↩️ وجه استرداد یافت!")
    await clear_dispute_chat_states(bot, state.storage, pid, project['client_id'], freelancer_id)

    # Send PDF Refund Receipt to both parties
    client_user = await db.get_user(project['client_id'])
    freelancer_user = await db.get_user(freelancer_id) if freelancer_id else None
    cl_name = (client_user['full_name'] or client_user['username'] or str(project['client_id'])) if client_user else str(project['client_id'])
    fl_name = (freelancer_user['full_name'] or freelancer_user['username'] or str(freelancer_id)) if freelancer_user else str(freelancer_id or 0)
    
    from handlers.common import send_invoice_to_parties
    await send_invoice_to_parties(
        bot=bot,
        project_id=pid,
        project_title=project['title'],
        client_id=project['client_id'],
        client_name=cl_name,
        freelancer_id=freelancer_id or 0,
        freelancer_name=fl_name,
        amount=amount,
        commission=0,
        payout=0,
        commission_pct=0,
        is_refund=True,
    )

    # Notify parties
    project_title = project['title'] if project else f"#{pid}"
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        
        # client keyboard
        cl_builder = InlineKeyboardBuilder()
        cl_builder.button(text="💰 مشاهده کیف پول", callback_data="wallet_menu_back")
        await bot.send_message(
            project['client_id'],
            f"⚖️ <b>رأی داوری: لغو و استرداد پروژه</b>\n"
            f"\n"
            f"📌 پروژه: <b>{project_title}</b>\n"
            f"💰 مبلغ بازگشتی: <b>{amount:,} تومان</b>\n"
            f"\n"
            f"با رأی داور حل اختلاف، پروژه لغو شده و هزینه به کیف پول شما بازگردانده شد.",
            reply_markup=cl_builder.as_markup(),
            parse_mode="HTML",
            message_effect_id="5046509860389126442"
        )
        
        if freelancer_id:
            fl_builder = InlineKeyboardBuilder()
            fl_builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
            await bot.send_message(
                freelancer_id,
                f"⚖️ <b>رأی داوری: لغو و استرداد پروژه</b>\n"
                f"\n"
                f"📌 پروژه: <b>{project_title}</b>\n"
                f"\n"
                f"با رأی داور حل اختلاف، پروژه لغو شده و وجه آن به کارفرما مسترد گردید. جهت پیگیری روی دکمه زیر کلیک کنید:",
                reply_markup=fl_builder.as_markup(),
                parse_mode="HTML"
            )
    except:
        pass


@router.callback_query(F.data.startswith("admin_withdrawals"))
async def admin_withdrawals_list(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    parts = callback.data.split("_")
    offset = int(parts[2]) if len(parts) > 2 else 0
    limit = 10
    
    total = await db.count_pending_withdrawals()
    if total == 0:
        await callback.message.edit_text(
            text=None,
            reply_markup=await get_admin_main_keyboard(),
            rich_message=InputRichMessage(html="📥 <b>هیچ درخواست تسویه در انتظاری وجود ندارد.</b>")
        )
        await callback.answer()
        return
        
    withdrawals = await db.get_pending_withdrawals_paginated(limit=limit, offset=offset)
    
    text = f"💸 <b>درخواست‌های تسویه حساب در انتظار تایید:</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for w in withdrawals:
        builder.button(
            text=f"درخواست #{w['withdrawal_id']} — {w['amount']:,}₸",
            callback_data=f"admin_view_withdraw_{w['withdrawal_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_withdrawals_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_withdrawals_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت", callback_data="admin_back_to_panel")
    
    adjust_pattern = [1] * len(withdrawals)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_view_withdraw_"))
async def admin_view_withdraw(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    wid = int(callback.data.split("_")[-1])
    w = await db.get_withdrawal(wid)
    if not w:
        return await callback.answer("درخواست یافت نشد.", show_alert=True)
    
    user = await db.get_user(w['user_id'])
    user_name = user['full_name'] or user['username'] or str(w['user_id']) if user else "نامشخص"
    
    html_content = (
        f"<h1>💸 جزئیات درخواست تسویه حساب #{wid}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>👤 کاربر</th><td>{user_name} (ID: <code>{w['user_id']}</code>)</td></tr>"
        f"  <tr><th>💰 مبلغ درخواستی</th><td>{w['amount']:,} تومان</td></tr>"
        f"  <tr><th>💳 شماره کارت</th><td><code>{w['card_number']}</code></td></tr>"
        f"  <tr><th>🏦 شماره شبا</th><td><code>{w['shaba']}</code></td></tr>"
        f"  <tr><th>📅 تاریخ درخواست</th><td>{to_shamsi(w['created_at'])}</td></tr>"
        f"  <tr><th>📊 وضعیت فعلی</th><td>{w['status']}</td></tr>"
        "</table>"
    )
    rich_msg = InputRichMessage(html=html_content)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    if w['status'] == 'pending':
        builder.button(text="✅ تایید و پرداخت", callback_data=f"admin_withdraw_approve_{wid}", style="success")
        builder.button(text="❌ رد درخواست", callback_data=f"admin_withdraw_reject_{wid}", style="danger")
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_withdrawals", style="primary")
    builder.adjust(2)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=rich_msg)
    await callback.answer()

@router.callback_query(F.data.startswith("admin_crm_user_"))
async def admin_crm_user(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    uid = int(callback.data.split("_")[-1])
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
        
    role_str = "کارفرما 👔" if user['role'] == 'client' else "فریلنسر 💻"
    vip_status = "فعال ⭐" if user['is_vip'] else "عادی 👤"
    ban_status = "مسدود 🚫" if user['is_banned'] else "فعال ✅"
    connects = user['connects'] if 'connects' in dict(user) else 5
    joined_shamsi = to_shamsi(user['joined_at'])
    
    username_val = f"@{user['username']}" if user['username'] else "ندارد"
    html_content = (
        f"<h1>👤 پروفایل مدیریتی: {user['full_name'] or 'بدون نام'}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>🆔 شناسه تلگرام</th><td><code>{user['user_id']}</code></td></tr>"
        f"  <tr><th>🏷 نام کاربری</th><td>{username_val}</td></tr>"
        f"  <tr><th>👔 نقش فعلی</th><td><b>{role_str}</b></td></tr>"
        f"  <tr><th>💵 موجودی کیف پول</th><td><b>{user['balance']:,} تومان</b></td></tr>"
        f"  <tr><th>🪙 موجودی کانکت (بید)</th><td><b>{connects}</b></td></tr>"
        f"  <tr><th>👑 اشتراک VIP</th><td><b>{vip_status}</b></td></tr>"
        f"  <tr><th>🚫 وضعیت حساب</th><td><b>{ban_status}</b></td></tr>"
        f"  <tr><th>📅 تاریخ عضویت</th><td>{joined_shamsi}</td></tr>"
        "</table>"
        "<br/>"
        "<p>💡 از گزینه‌های زیر برای مدیریت حساب این کاربر استفاده کنید:</p>"
    )
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    
    # Toggle Ban Button
    ban_btn_text = "🟢 رفع مسدودیت" if user['is_banned'] else "🔴 مسدود کردن کاربر"
    builder.button(text=ban_btn_text, callback_data=f"admin_crm_toggle_ban_{uid}")
    
    # Toggle VIP Button
    vip_btn_text = "❌ لغو اشتراک VIP" if user['is_vip'] else "👑 فعالسازی اشتراک VIP"
    builder.button(text=vip_btn_text, callback_data=f"admin_crm_toggle_vip_{uid}")
    
    # Balance Adjustment Button
    builder.button(text="✍️ تغییر موجودی کیف پول", callback_data=f"admin_crm_edit_bal_{uid}")
    
    # Connects Adjustment Button
    builder.button(text="🪙 تغییر موجودی کانکت (بید)", callback_data=f"admin_crm_edit_conn_{uid}")
    
    # Transactions & Projects Buttons
    builder.button(text="📜 مشاهده تراکنش‌های اخیر کاربر", callback_data=f"admin_crm_view_txs_{uid}")
    builder.button(text="📌 مشاهده پروژه‌های فعال کاربر", callback_data=f"admin_crm_view_projs_{uid}")
    
    # Back to list
    builder.button(text="🔙 بازگشت به لیست کاربران", callback_data="admin_users")
    
    builder.adjust(1)
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=html_content))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_crm_toggle_ban_"))
async def admin_crm_toggle_ban(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    uid = int(callback.data.split("_")[-1])
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
        
    if user['is_banned']:
        await db.unban_user(uid)
        await callback.answer("✅ کاربر فعال شد.")
    else:
        await db.ban_user(uid)
        await callback.answer("🚫 کاربر مسدود شد.")
        
    # Re-render CRM profile
    callback.data = f"admin_crm_user_{uid}"
    await admin_crm_user(callback, None)


@router.callback_query(F.data.startswith("admin_crm_toggle_vip_"))
async def admin_crm_toggle_vip(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    uid = int(callback.data.split("_")[-1])
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
        
    if user['is_vip']:
        import aiosqlite
        from config import DB_PATH
        async with aiosqlite.connect(DB_PATH) as conn:
            await conn.execute("UPDATE users SET is_vip = 0, vip_expiry = NULL WHERE user_id = ?", (uid,))
            await conn.commit()
        await callback.answer("❌ اشتراک VIP لغو شد.")
    else:
        await db.activate_vip(uid, months=1)
        await callback.answer("👑 اشتراک VIP برای یک ماه فعال شد.")
        
    # Refresh
    callback.data = f"admin_crm_user_{uid}"
    await admin_crm_user(callback, None)


@router.callback_query(F.data.startswith("admin_crm_view_txs_"))
async def admin_crm_view_txs(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    parts = callback.data.split("_")
    uid = int(parts[4])
    offset = int(parts[5]) if len(parts) > 5 else 0
    limit = 10
    
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
    
    total = await db.count_user_transactions(uid)
    if total == 0:
        return await callback.answer("هیچ تراکنشی برای این کاربر ثبت نشده است.", show_alert=True)
        
    txs = await db.get_user_transactions_paginated(uid, limit=limit, offset=offset)
    
    html_content = (
        f"<h1>📜 تاریخچه تراکنش‌های کاربر: {user['full_name'] or 'بدون نام'}</h1>"
        "<hr/>"
        "<table bordered striped>"
        "  <tr><th>نوع</th><th>مبلغ (تومان)</th><th>توضیحات</th><th>تاریخ</th></tr>"
    )
    for t in txs:
        date_shamsi = to_shamsi(t['created_at'])
        amount_formatted = f"{t['amount']:,}" if t['amount'] >= 0 else f"({abs(t['amount']):,})"
        html_content += f"  <tr><td>{t['tx_type']}</td><td>{amount_formatted}</td><td>{t['description']}</td><td>{date_shamsi}</td></tr>"
    html_content += "</table>"
    html_content += f"<br/><p>صفحه {offset // limit + 1} از {(total - 1) // limit + 1}</p>"
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_crm_view_txs_{uid}_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_crm_view_txs_{uid}_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت به پروفایل کاربر", callback_data=f"admin_crm_user_{uid}")
    
    if nav_count == 2:
        builder.adjust(2, 1)
    else:
        builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=html_content))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_crm_view_projs_"))
async def admin_crm_view_projs(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    parts = callback.data.split("_")
    uid = int(parts[4])
    offset = int(parts[5]) if len(parts) > 5 else 0
    limit = 10
    
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
        
    total = await db.count_active_projects_by_user(uid)
    if total == 0:
        return await callback.answer("هیچ پروژه فعال یا در جریانی برای این کاربر یافت نشد.", show_alert=True)
        
    projects = await db.get_active_projects_by_user_paginated(uid, limit=limit, offset=offset)
        
    html_content = (
        f"<h1>📌 پروژه‌های فعال/جاری کاربر: {user['full_name'] or 'بدون نام'}</h1>"
        "<hr/>"
        "<table bordered>"
        "  <tr><th>آیدی</th><th>عنوان پروژه</th><th>وضعیت</th><th>بودجه (تومان)</th></tr>"
    )
    from utils.texts import PROJECT_STATUS_MAP
    for p in projects:
        status_farsi = PROJECT_STATUS_MAP.get(p['status'], p['status'])
        html_content += f"  <tr><td>#{p['project_id']}</td><td>{p['title']}</td><td>{status_farsi}</td><td>{p['budget_min']:,} - {p['budget_max']:,}</td></tr>"
    html_content += "</table>"
    html_content += f"<br/><p>صفحه {offset // limit + 1} از {(total - 1) // limit + 1}</p>"
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_crm_view_projs_{uid}_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_crm_view_projs_{uid}_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت به پروفایل کاربر", callback_data=f"admin_crm_user_{uid}")
    
    if nav_count == 2:
        builder.adjust(2, 1)
    else:
        builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=html_content))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_crm_edit_bal_"))
async def admin_crm_edit_bal(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    uid = int(callback.data.split("_")[-1])
    from states.forms import AdminChangeBalance
    await state.update_data(crm_target_uid=uid)
    await state.set_state(AdminChangeBalance.waiting_for_amount)
    
    await callback.message.answer(
        "✍️ <b>تغییر موجودی کیف پول</b>\n\n"
        "لطفا مبلغ مابه التفاوت را وارد کنید (فقط عدد):\n"
        "به عنوان مثال، برای افزایش ۵۰,۰۰۰ تومان بنویسید `50000` و برای کاهش آن بنویسید `-50000`:",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()


@router.message(AdminChangeBalance.waiting_for_amount)
async def process_admin_crm_change_balance(message: Message, state: FSMContext, db_user):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
        
    data = await state.get_data()
    uid = data.get("crm_target_uid")
    await state.clear()
    
    text_clean = message.text.strip()
    is_negative = text_clean.startswith("-")
    digits_part = text_clean.lstrip("-")
    
    if not digits_part.isdigit():
        return await message.answer("❌ خطا! لطفا فقط یک عدد صحیح معتبر وارد کنید.")
        
    amount = int(digits_part)
    if is_negative:
        amount = -amount
        
    try: await message.react([ReactionTypeEmoji(emoji="💰")])
    except: pass
    await db.update_balance(uid, amount, "admin_adjustment", "تغییر موجودی توسط مدیریت")
    
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    role = db_user['role'] or 'freelancer'
    kb = reply.client_main_menu(is_admin=is_admin) if role == 'client' else reply.freelancer_main_menu(is_admin=is_admin)
    
    user = await db.get_user(uid)
    name = user['full_name'] or user['username'] or str(uid)
    await message.answer(
        f"✅ تراکنش با موفقیت ثبت شد!\n"
        f"موجودی جدید کاربر {name}: <b>{user['balance']:,} تومان</b>",
        reply_markup=kb,
        parse_mode="HTML"
    )


@router.callback_query(F.data.startswith("admin_crm_edit_conn_"))
async def admin_crm_edit_conn(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    uid = int(callback.data.split("_")[-1])
    from states.forms import AdminChangeConnects
    await state.update_data(crm_target_uid=uid)
    await state.set_state(AdminChangeConnects.waiting_for_amount)
    
    await callback.message.answer(
        "✍️ <b>تغییر موجودی کانکت (بید)</b>\n\n"
        "لطفاً مقدار تغییر کانکت را وارد کنید (فقط عدد):\n"
        "به عنوان مثال، برای افزایش ۵ کانکت بنویسید `5` و برای کاهش آن بنویسید `-5`:",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()


@router.message(AdminChangeConnects.waiting_for_amount)
async def process_admin_crm_change_connects(message: Message, state: FSMContext, db_user):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
        
    data = await state.get_data()
    uid = data.get("crm_target_uid")
    await state.clear()
    
    text_clean = message.text.strip()
    is_negative = text_clean.startswith("-")
    digits_part = text_clean.lstrip("-")
    
    if not digits_part.isdigit():
        return await message.answer("❌ خطا! لطفا فقط یک عدد صحیح معتبر وارد کنید.")
        
    amount = int(digits_part)
    if is_negative:
        amount = -amount
        
    try: await message.react([ReactionTypeEmoji(emoji="🪙")])
    except: pass
    await db.update_connects(uid, amount, "admin_adjustment_connects", "تغییر کانکت توسط مدیریت")
    
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    role = db_user['role'] or 'freelancer'
    kb = reply.client_main_menu(is_admin=is_admin) if role == 'client' else reply.freelancer_main_menu(is_admin=is_admin)
    
    user = await db.get_user(uid)
    name = user['full_name'] or user['username'] or str(uid)
    connects = user['connects'] if 'connects' in dict(user) else 0
    await message.answer(
        f"✅ تراکنش کانکت با موفقیت ثبت شد!\n"
        f"موجودی جدید کانکت کاربر {name}: <b>{connects} کانکت</b>",
        reply_markup=kb,
        parse_mode="HTML"
    )


@router.callback_query(F.data == "admin_search_user")
async def admin_search_user_start(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    from states.forms import AdminUserSearch
    await state.set_state(AdminUserSearch.waiting_for_query)
    await callback.message.answer(
        "🔎 <b>جستجوی کاربر در سیستم</b>\n\n"
        "لطفا بخشی از نام کاربر، نام کاربری (username بدون @) یا شناسه عددی تلگرام کاربر را بنویسید:",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()


@router.message(AdminUserSearch.waiting_for_query)
async def process_admin_user_search(message: Message, state: FSMContext, db_user):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
        
    query = message.text.strip()
    await state.clear()
    
    try: await message.react([ReactionTypeEmoji(emoji="🔍")])
    except: pass
    users = await db.search_users(query)
    
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    role = db_user['role'] or 'freelancer'
    kb = reply.client_main_menu(is_admin=is_admin) if role == 'client' else reply.freelancer_main_menu(is_admin=is_admin)
    
    if not users:
        return await message.answer("❌ هیچ کاربری منطبق با جستجوی شما یافت نشد.", reply_markup=kb)
        
    text = f"🔎 <b>نتایج جستجو برای «{query}» (حداکثر ۱۰ کاربر):</b>\nبرای مدیریت، روی دکمه هر کاربر کلیک کنید:"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for u in users:
        role_icon = "👔" if u['role'] == 'client' else "💻"
        vip_icon = "⭐" if u['is_vip'] else ""
        name = u['full_name'] or u['username'] or str(u['user_id'])
        builder.button(
            text=f"{role_icon}{vip_icon} {name}",
            callback_data=f"admin_crm_user_{u['user_id']}"
        )
    builder.button(text="🔙 بازگشت به پنل", callback_data="admin_back_to_panel")
    builder.adjust(1)
    
    await message.answer(text, reply_markup=builder.as_markup(), parse_mode="HTML")


# ── Dispute Management (Arbitration Queue) ───────────────────────────

@router.callback_query(F.data.startswith("admin_disputes"))
async def admin_disputes_list(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    parts = callback.data.split("_")
    offset = int(parts[2]) if len(parts) > 2 else 0
    limit = 10
    
    total = await db.count_disputed_projects()
    if total == 0:
        await callback.message.edit_text(
            text=None,
            reply_markup=inline.admin_keyboard(),
            rich_message=InputRichMessage(html="⚖️ <b>هیچ پروژه مورد اختلافی (شکایت باز) وجود ندارد.</b>")
        )
        await callback.answer()
        return
        
    disputes = await db.get_disputed_projects_paginated(limit=limit, offset=offset)
        
    text = f"⚖️ <b>لیست پروژه‌های دارای شکایت / در حال داوری:</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}\n\nروی پروژه کلیک کنید تا پرونده داوری باز شود:"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for p in disputes:
        builder.button(
            text=f"⚖️ #{p['project_id']} — {p['title'][:30]}",
            callback_data=f"admin_view_dispute_{p['project_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_disputes_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_disputes_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت", callback_data="admin_back_to_panel")
    
    adjust_pattern = [1] * len(disputes)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_view_dispute_"))
async def admin_view_dispute(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
    project = dict(project)
        
    import aiosqlite
    from config import DB_PATH
    escrow = None
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT * FROM escrow WHERE project_id = ?', (pid,)) as cursor:
                escrow = await cursor.fetchone()
    except Exception:
        pass
        
    amount = escrow['amount'] if escrow else 0
    client = await db.get_user(project['client_id'])
    freelancer = await db.get_user(project['chosen_freelancer_id'])
    
    client_name = client['full_name'] or client['username'] or str(project['client_id']) if client else "نامشخص"
    freelancer_name = freelancer['full_name'] or freelancer['username'] or str(project['chosen_freelancer_id']) if freelancer else "نامشخص"
    
    html_content = (
        f"<h1>⚖️ پرونده داوری پروژه #{pid}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>📌 عنوان پروژه</th><td>{project['title']}</td></tr>"
        f"  <tr><th>👔 کارفرما</th><td>{client_name} (ID: <code>{project['client_id']}</code>)</td></tr>"
        f"  <tr><th>💻 فریلنسر استخدام شده</th><td>{freelancer_name} (ID: <code>{project['chosen_freelancer_id']}</code>)</td></tr>"
        f"  <tr><th>💰 بودجه درگیر (Escrow)</th><td>{amount:,} تومان</td></tr>"
        "</table>"
        "<br/>"
        "<h3>📋 توضیحات پروژه:</h3>"
        f"<blockquote>{project['description']}</blockquote>"
        "<br/>"
        "<h3>📦 توضیحات فایل تحویل شده:</h3>"
        f"<blockquote>{project.get('delivery_text') or '_تحویل نشده_'}</blockquote>"
    )
    
    # Append last 5 chat messages
    try:
        chat_messages = await db.get_project_chat_summary(pid, limit=5)
        if chat_messages:
            html_content += (
                "<br/>"
                "<h3>💬 آخرین مکاتبات پروژه (۵ پیام اخیر):</h3>"
                "<table bordered striped>"
                "  <tr><th>فرستنده</th><th>پیام</th></tr>"
            )
            for msg in chat_messages:
                sender = msg['sender_name'] if 'sender_name' in msg.keys() else "ناشناس"
                text = str(msg['content'] if 'content' in msg.keys() else msg['text'] if 'text' in msg.keys() else "—")
                # Truncate long messages
                text_truncated = text[:120] + "…" if len(text) > 120 else text
                html_content += f"  <tr><td><b>{sender}</b></td><td>{text_truncated}</td></tr>"
            html_content += "</table>"
        else:
            html_content += (
                "<br/>"
                "<h3>💬 آخرین مکاتبات پروژه:</h3>"
                "<p><i>هیچ پیامی در چت پروژه یافت نشد.</i></p>"
            )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Error fetching chat summary for dispute {pid}: {e}")
    rich_msg = InputRichMessage(html=html_content)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🗳 داوری و تسویه اختلاف", callback_data=f"admin_dispute_settle_menu_{pid}", style="success")
    builder.button(text="💬 ورود به چت داوری سه‌نفره", callback_data=f"admin_enter_dispute_chat_{pid}", style="primary")
    import hashlib
    bot_domain = await db.get_setting('bot_domain', 'http://127.0.0.1:8000')
    expected_token = hashlib.sha256(f"Xlancer_Secret_{pid}".encode()).hexdigest()
    
    from aiogram.types import WebAppInfo
    builder.button(text="🔍 مشاهده چت‌ها در مینی‌اپ", web_app=WebAppInfo(url=f"{bot_domain}/dispute_chat?project_id={pid}&token={expected_token}"))
    builder.button(text="🗳 ارجاع به هیئت داوران (Jury)", callback_data=f"admin_refer_jury_{pid}", style="primary")
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_disputes", style="primary")
    builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=rich_msg)
    await callback.answer()

@router.callback_query(F.data.startswith("admin_dispute_transcript_") | F.data.startswith("jury_dispute_transcript_"))
async def get_dispute_transcript_handler(callback: CallbackQuery, bot: Bot):
    parts = callback.data.split("_")
    pid = int(parts[-1])
    
    is_juror = parts[0] == "jury"
    if not is_juror and not admin_only(callback.from_user.id):
         return await callback.answer("دسترسی ندارید.", show_alert=True)
         
    transcript = await db.get_project_chat_transcript(pid)
    
    from aiogram.types import BufferedInputFile
    file_content = transcript.encode('utf-8')
    file_input = BufferedInputFile(file_content, filename=f"dispute_chat_{pid}.txt")
    
    try:
        await bot.send_document(
            chat_id=callback.from_user.id,
            document=file_input,
            caption=f"📜 تاریخچه مکالمات پروژه #{pid}"
        )
        await callback.answer("✅ تاریخچه گفتگو ارسال شد.")
    except Exception as e:
        logger = __import__('logging').getLogger(__name__)
        logger.error(f"Error sending transcript file: {e}")
        await callback.answer("❌ خطا در ارسال فایل تاریخچه.", show_alert=True)

@router.callback_query(F.data.startswith("admin_refer_jury_"))
async def admin_refer_jury(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
    
    # Check if jury case already exists
    existing = await db.get_jury_case(pid)
    if existing:
        return await callback.answer("⚠️ این پرونده قبلاً به هیئت داوران ارجاع شده است.", show_alert=True)
    
    # Warn admin and suggest arbitrating directly first
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🗳 بله، ارجاع عمومی به هیئت داوران", callback_data=f"admin_confirm_refer_jury_{pid}", style="danger")
    builder.button(text="🔙 خیر، بررسی چت و تسویه مستقیم", callback_data=f"admin_view_dispute_{pid}", style="primary")
    builder.adjust(1)
    
    warn_text = (
        f"⚠️ <b>داور گرامی (ادمین):</b>\n\n"
        f"پیشنهاد می‌شود پیش از ارجاع پرونده به هیئت منصفه عمومی (Jury)، ابتدا با ورود به چت داوری سه‌نفره یا بررسی مدارک و پیام‌ها، سعی کنید اختلاف را <b>شخصاً و به صورت مستقیم</b> حل و تسویه کنید.\n\n"
        f"آیا با وجود بررسی، همچنان مایل به ارجاع پرونده به هیئت داوران و رأی‌گیری عمومی هستید؟"
    )
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=warn_text))
    await callback.answer()

@router.callback_query(F.data.startswith("admin_confirm_refer_jury_"))
async def admin_confirm_refer_jury(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
    
    # Check if jury case already exists
    existing = await db.get_jury_case(pid)
    if existing:
        return await callback.answer("⚠️ این پرونده قبلاً به هیئت داوران ارجاع شده است.", show_alert=True)
    
    # Create jury case
    await db.create_jury_case(pid)
    
    # Get eligible jurors (exclude parties)
    exclude = [project['client_id'], project['chosen_freelancer_id']]
    jurors = await db.get_eligible_jurors(exclude_ids=exclude)
    
    if not jurors:
        await callback.answer("⚠️ هیچ فریلنسر واجد شرایطی برای داوری یافت نشد.", show_alert=True)
        return
    
    # Prepare anonymous dispute card
    import aiosqlite
    from config import DB_PATH
    escrow_amount = 0
    try:
        async with aiosqlite.connect(DB_PATH) as conn:
            conn.row_factory = aiosqlite.Row
            async with conn.execute('SELECT amount FROM escrow WHERE project_id = ?', (pid,)) as cursor:
                row = await cursor.fetchone()
                escrow_amount = row['amount'] if row else 0
    except Exception:
        pass
    
    card_html = (
        f"<h1>🗳 درخواست داوری — پرونده #{pid}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>📌 عنوان پروژه</th><td>{project['title']}</td></tr>"
        f"  <tr><th>💰 مبلغ درگیر</th><td>{escrow_amount:,} تومان</td></tr>"
        f"  <tr><th>🎁 پاداش داوری</th><td>۵,۰۰۰ تومان + ۵ کانکت</td></tr>"
        "</table>"
        "<br/>"
        "<h3>📝 توضیحات پروژه:</h3>"
        f"<blockquote>{(project['description'] or '')[:200]}...</blockquote>"
        "<br/>"
        "<h3>📦 تحویلی‌ها:</h3>"
        f"<blockquote>{project.get('delivery_text') or 'ثبت نشده'}</blockquote>"
        "<br/>"
        "<p>⚖️ <b>لطفاً با بررسی اطلاعات بالا، رأی خود را ثبت کنید:</b><br/>"
        "🔓 آزادسازی = فریلنسر کار را انجام داده<br/>"
        "↩️ استرداد = کارفرما حق دارد</p>"
    )
    rich_msg = InputRichMessage(html=card_html)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    vote_kb = InlineKeyboardBuilder()
    vote_kb.button(text="🔓 آزادسازی به فریلنسر", callback_data=f"jury_vote_{pid}_release")
    vote_kb.button(text="↩️ استرداد به کارفرما", callback_data=f"jury_vote_{pid}_refund")
    import hashlib
    bot_domain = await db.get_setting('bot_domain', 'http://127.0.0.1:8000')
    expected_token = hashlib.sha256(f"Xlancer_Secret_{pid}".encode()).hexdigest()
    
    from aiogram.types import WebAppInfo
    vote_kb.button(text="🔍 مشاهده چت‌ها در مینی‌اپ", web_app=WebAppInfo(url=f"{bot_domain}/dispute_chat?project_id={pid}&token={expected_token}"))
    vote_kb.adjust(1)
    
    juror_ids = [j['user_id'] for j in jurors]
    
    from utils.broadcaster import safe_broadcast
    import asyncio
    
    asyncio.create_task(
        safe_broadcast(
            bot=bot,
            user_ids=juror_ids,
            reply_markup=vote_kb.as_markup(),
            rich_message=rich_msg
        )
    )
    
    html_msg = f"⚖️ <b>پرونده با موفقیت به هیئت داوران ارجاع شد.</b>\n\nتعداد داوران فراخوانده‌شده: {len(juror_ids)} نفر\nحدنصاب آرا: {db.JURY_QUORUM} رأی"
    await callback.message.edit_text(
        text=None,
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer(f"✅ کارت داوری برای {len(juror_ids)} داور ارسال شد.")

@router.callback_query(F.data.startswith("admin_enter_dispute_chat_"))
async def admin_enter_dispute_chat(callback: CallbackQuery, state: FSMContext, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    # Set this admin as the dispute chat admin
    await db.set_dispute_chat_admin(pid, callback.from_user.id)
    
    # Set FSM state
    await state.set_state(DisputeChat.in_chat)
    await state.update_data(project_id=pid)
    
    # Provide inline controls keyboard for admin (persistent controls)
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    admin_chat_controls = InlineKeyboardBuilder()
    admin_chat_controls.button(text="🔓 آزادسازی به نفع فریلنسر", callback_data=f"admin_escrow_release_{pid}")
    admin_chat_controls.button(text="↩️ استرداد به کارفرما", callback_data=f"admin_escrow_refund_{pid}")
    admin_chat_controls.button(text="🚪 خروج از چت داوری", callback_data=f"admin_exit_dispute_chat")
    admin_chat_controls.adjust(1)
    
    # Send welcome text
    welcome_text = (
        f"⚖️ <b>شما به عنوان داور (ادمین) وارد چت داوری پروژه #{pid} شدید.</b>\n\n"
        f"پیام‌های شما برای کارفرما و فریلنسر پروژه ارسال می‌شود.\n"
        f"می‌توانید با استفاده از دکمه‌های زیر رأی نهایی را صادر کنید:"
    )
    
    from keyboards.reply import dispute_chat_keyboard
    await callback.message.answer(
        welcome_text,
        reply_markup=dispute_chat_keyboard(),
        parse_mode="HTML"
    )
    await callback.message.answer(
        "⚖️ <b>پنل رأی داوری:</b>",
        reply_markup=admin_chat_controls.as_markup(),
        parse_mode="HTML"
    )
    await callback.answer("وارد چت داوری شدید.")

@router.callback_query(F.data == "admin_exit_dispute_chat")
async def admin_exit_dispute_chat(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    await callback.message.answer("⚖️ شما از چت داوری خارج شدید. به پنل مدیریت بازمی‌گردید.")
    # Show admin panel
    stats = await db.get_platform_stats()
    text = (
        "👑 <b>به پنل مدیریت ایکس‌لنسر خوش آمدید</b>\n\n"
        f"👥 <b>کل کاربران:</b> {stats['users_count']} نفر\n"
        f"📌 <b>پروژه‌های فعال:</b> {stats['active_projects']} پروژه\n"
        f"🔒 <b>مبلغ بلوکه‌شده در صندوق (Escrow):</b> {stats['escrow_sum']:,} تومان\n"
        f"💰 <b>مجموع درآمد پلتفرم (کمیسیون):</b> {stats['earnings']:,} تومان\n\n"
        "یک گزینه را انتخاب کنید:"
    )
    await callback.message.answer(text, reply_markup=await get_admin_main_keyboard(), parse_mode="HTML")
    await callback.answer()

async def clear_dispute_chat_states(bot: Bot, storage, project_id: int, client_id: int, freelancer_id: int):
    admin_id = None
    try:
        chat_info = await db.get_dispute_chat(project_id)
        if chat_info:
            admin_id = chat_info['admin_id']
    except Exception:
        pass

    from aiogram.fsm.storage.base import StorageKey
    bot_id = bot.id
    for uid in [client_id, freelancer_id, admin_id]:
        if not uid:
            continue
        key = StorageKey(bot_id=bot_id, chat_id=uid, user_id=uid)
        try:
            current_state = await storage.get_state(key)
            if current_state == DisputeChat.in_chat.state:
                data = await storage.get_data(key)
                if data.get("project_id") == project_id:
                    await storage.set_state(key, None)
                    await storage.set_data(key, {})
                    
                    db_user = await db.get_user(uid)
                    if db_user:
                        if uid in ADMIN_IDS:
                            await bot.send_message(
                                uid,
                                f"⚖️ <b>جلسه چت داوری پروژه #{project_id} خاتمه یافت و بسته شد.</b>",
                                parse_mode="HTML"
                            )
                        else:
                            from keyboards import reply
                            role = db_user['role']
                            is_admin = uid in ADMIN_IDS
                            kb = reply.client_main_menu(is_admin=is_admin) if role == 'client' else reply.freelancer_main_menu(is_admin=is_admin)
                            await bot.send_message(
                                uid,
                                f"⚖️ <b>جلسه چت داوری پروژه #{project_id} خاتمه یافت و بسته شد.</b>\nبه منوی اصلی بازگشتید.",
                                reply_markup=kb,
                                parse_mode="HTML"
                            )
        except Exception:
            pass

# ── Admin Platform Settings ───────────────────────────────────────────

@router.callback_query(F.data == "admin_platform_settings")
async def show_platform_settings(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    await state.clear()
    html_msg = (
        "<h1>⚙️ تنظیمات پلتفرم ایکس‌لنسر</h1>"
        "<hr/>"
        "<p>یکی از دسته‌بندی‌های زیر را انتخاب کنید:</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_settings_categories_keyboard(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer()

@router.callback_query(F.data.startswith("admin_settings_cat_"))
async def show_settings_category(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    category = callback.data.replace("admin_settings_cat_", "")
    await state.update_data(settings_current_cat=category)
    
    cat_names = {
        'tariffs': '💰 تعرفه‌ها و هزینه‌ها',
        'connects': '🪙 کانکت‌ها و هدایا',
        'gateways': '💳 درگاه‌های پرداخت',
        'general': '📢 تنظیمات عمومی کانال',
        'groups': '👥 گروه‌های بررسی ادمین'
    }
    cat_name = cat_names.get(category, category)
    
    settings = await db.get_all_settings()
    html_msg = (
        f"<h1>⚙️ تنظیمات دسته: {cat_name}</h1>"
        "<hr/>"
        "<p>برای ویرایش هر مقدار روی آن کلیک کنید:</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_settings_keyboard(settings, category),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer()

@router.callback_query(F.data.startswith("admin_toggle_setting_"))
async def toggle_setting_handler(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    data_str = callback.data[21:]
    r_parts = data_str.rsplit("_", 1)
    key = r_parts[0]
    category = r_parts[1]
    
    current_val = await db.get_setting(key, '0')
    new_val = '0' if current_val == '1' else '1'
    await db.update_setting(key, new_val)
    
    cat_names = {
        'tariffs': '💰 تعرفه‌ها و هزینه‌ها',
        'connects': '🪙 کانکت‌ها و هدایا',
        'gateways': '💳 درگاه‌های پرداخت',
        'general': '📢 تنظیمات عمومی ربات',
        'groups': '👥 گروه‌های بررسی ادمین'
    }
    cat_name = cat_names.get(category, category)
    
    settings = await db.get_all_settings()
    html_msg = (
        f"<h1>⚙️ تنظیمات دسته: {cat_name}</h1>"
        "<hr/>"
        "<p>برای ویرایش هر مقدار روی آن کلیک کنید:</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_settings_keyboard(settings, category),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("تنظیمات با موفقیت تغییر یافت.")

@router.callback_query(F.data.startswith("admin_edit_setting_"))
async def start_edit_setting(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    key = callback.data.replace("admin_edit_setting_", "")
    val = await db.get_setting(key)
    from keyboards.inline import SETTINGS_LABELS
    label = SETTINGS_LABELS.get(key, key)
    await state.update_data(setting_key=key)
    await state.set_state(AdminSettings.waiting_for_setting_value)
    
    if key.startswith('admin_group_'):
        current_display = val if val else "❌ پیش‌فرض (همه ادمین‌ها)"
        msg_text = (
            f"✍️ <b>ویرایش تنظیمات:</b> `{label}`\n\n"
            f"مقدار فعلی: `{current_display}`\n\n"
            f"ℹ️ راهنما: شما می‌توانید آیدی‌های عددی گروه‌ها (مانند <code>-100123456789</code>) یا آیدی‌های عمومی (مانند <code>@group_username</code>) را ارسال کنید.\n"
            f"برای وارد کردن چند گروه، آن‌ها را با کاما (,) جدا کنید (مثال: <code>-1001234567,-100987654</code>).\n"
            f"برای بازنشانی به حالت پیش‌فرض (ارسال به پی‌وی تمام ادمین‌ها)، کلمه <b>حذف</b> یا <b>خالی</b> را بفرستید.\n\n"
            f"لطفاً مقدار جدید را ارسال کنید:"
        )
    else:
        msg_text = (
            f"✍️ <b>ویرایش تنظیمات:</b> `{label}`\n\n"
            f"مقدار فعلی: `{val}`\n"
            f"لطفاً مقدار جدید را ارسال کنید:"
        )
        
    await callback.message.answer(
        msg_text,
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()

@router.message(AdminSettings.waiting_for_setting_value)
async def save_setting_value(message: Message, state: FSMContext):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
    data = await state.get_data()
    key = data['setting_key']
    current_cat = data.get('settings_current_cat', 'tariffs')
    
    new_val = message.text.strip()
    
    # Input validation
    if key in ['commission_free', 'commission_vip', 'commission_bronze', 'commission_silver', 'commission_gold']:
        try:
            val = float(new_val)
            if not (0 <= val <= 1.0):
                return await message.answer("⚠️ مقدار کمیسیون باید عددی بین 0 و 1 (مثال: 0.10 برای 10 درصد) باشد. دوباره تلاش کنید:")
        except ValueError:
            return await message.answer("⚠️ لطفاً یک عدد اعشاری معتبر وارد کنید (مثال: 0.05). دوباره تلاش کنید:")
    elif key in ['vip_monthly_price', 'vip_bronze_price', 'vip_silver_price', 'vip_gold_price', 'featured_project_price', 'max_free_bids', 'connects_monthly_bronze', 'connects_monthly_silver', 'connects_monthly_gold', 'invite_reward', 'default_connects', 'invite_connects', 'bid_pack_10_price', 'bid_pack_30_price', 'bid_pack_100_price', 'fulltime_project_price', 'min_project_budget', 'min_wallet_deposit', 'min_wallet_withdraw']:
        if not new_val.isdigit():
            return await message.answer("⚠️ لطفاً یک عدد صحیح و مثبت وارد کنید. دوباره تلاش کنید:")
    elif key == 'bot_status':
        if new_val not in ['0', '1']:
            return await message.answer("⚠️ وضعیت ربات فقط می‌تواند ۰ (غیرفعال/تعمیرات) یا ۱ (فعال) باشد. دوباره تلاش کنید:")
    elif key == 'join_mandatory':
        if new_val not in ['0', '1']:
            return await message.answer("⚠️ وضعیت عضویت اجباری فقط می‌تواند ۰ (خاموش) یا ۱ (روشن) باشد. دوباره تلاش کنید:")
    elif key == 'channel_id':
        is_username = new_val.startswith('@') and len(new_val) > 1
        is_url = new_val.startswith('http://') or new_val.startswith('https://') or new_val.startswith('t.me/')
        is_numeric = (new_val.startswith('-') and new_val[1:].isdigit()) or new_val.isdigit()
        if not (is_username or is_url or is_numeric):
            return await message.answer("⚠️ آیدی کانال نامعتبر است. باید با @ شروع شود (مانند @xlancer_jobs)، یا یک لینک معتبر باشد، یا یک آیدی عددی باشد (مانند -100123456). دوباره تلاش کنید:")
    elif key in ['bot_domain', 'payment_callback_domain']:
        if not (new_val.startswith('http://') or new_val.startswith('https://')):
            return await message.answer("⚠️ دامنه باید یک URL معتبر باشد که با http:// یا https:// شروع می‌شود. دوباره تلاش کنید:")
    elif key == 'admin_card':
        if not new_val.isdigit() or len(new_val) != 16:
            return await message.answer("⚠️ شماره کارت باید دقیقاً ۱۶ رقم عددی باشد. دوباره تلاش کنید:")
    elif key == 'admin_card_name':
        if len(new_val) < 3:
            return await message.answer("⚠️ نام صاحب کارت باید حداقل ۳ کاراکتر باشد. دوباره تلاش کنید:")
    elif key.startswith('admin_group_'):
        if new_val.lower() in ["خالی", "حذف", "none", "default", "پیش فرض", "پیش‌فرض", "0", "-0"]:
            new_val = ""
        elif new_val != "":
            parts = [p.strip() for p in new_val.split(',') if p.strip()]
            if not parts:
                return await message.answer("⚠️ لطفاً حداقل یک آیدی عددی معتبر (مثلاً 100123456- یا آیدی با @) یا عبارت 'حذف' را وارد کنید. دوباره تلاش کنید:")
            for p in parts:
                is_int = p.isdigit() or (p.startswith('-') and p[1:].isdigit())
                is_username = p.startswith('@') and len(p) > 1
                if not (is_int or is_username):
                    return await message.answer("⚠️ آیدی گروه/کانال فقط می‌تواند عدد (با علامت منفی اختیاری)، آیدی با @، یا عبارت 'حذف' باشد. دوباره تلاش کنید:")

    await state.clear()
    try: await message.react([ReactionTypeEmoji(emoji="⚙️")])
    except: pass
    await db.update_setting(key, new_val)
    
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    await message.answer(
        "✅ تنظیمات با موفقیت بروزرسانی شد.",
        reply_markup=reply.client_main_menu(is_admin=is_admin),
        parse_mode="HTML"
    )
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="⚙️ بازگشت به تنظیمات", callback_data=f"admin_settings_cat_{current_cat}")
    builder.button(text="🔙 بازگشت به پنل ادمین", callback_data="admin_back_to_panel")
    builder.adjust(1)
    
    display_val = new_val if new_val else "❌ پیش‌فرض (همه ادمین‌ها)"
    await message.answer(
        f"تنظیم <b>{key}</b> به مقدار جدید <code>{display_val}</code> تغییر یافت.",
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )

# ── User Verification Requests ──────────────────────────────────────────

@router.callback_query(F.data.startswith("admin_pending_verifications"))
async def list_pending_verifications(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    parts = callback.data.split("_")
    offset = int(parts[3]) if len(parts) > 3 else 0
    limit = 10
    
    total = await db.count_pending_verifications()
    if total == 0:
        return await callback.message.edit_text(
            text=None,
            reply_markup=await get_admin_main_keyboard(),
            rich_message=InputRichMessage(html="🔐 <b>هیچ درخواست احراز هویت در انتظاری وجود ندارد.</b>")
        )
        
    reqs = await db.get_pending_verifications_paginated(limit=limit, offset=offset)
    
    text = f"🔐 <b>درخواست‌های احراز هویت در انتظار تایید:</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for r in reqs:
        builder.button(
            text=f"👤 {r['full_name']} — {r['phone_number']}",
            callback_data=f"admin_view_verify_{r['user_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_pending_verifications_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_pending_verifications_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت", callback_data="admin_back_to_panel")
    
    adjust_pattern = [1] * len(reqs)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()

@router.callback_query(F.data.startswith("admin_view_verify_"))
async def view_pending_verification(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    uid = int(callback.data.split("_")[-1])
    user = await db.get_user(uid)
    if not user:
        return await callback.answer("کاربر یافت نشد.", show_alert=True)
        
    html_content = (
        f"<h1>🔐 درخواست احراز هویت</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>👤 کاربر</th><td>{user['full_name']} (ID: <code>{uid}</code>)</td></tr>"
        f"  <tr><th>🏷 نام کاربری</th><td>@{user['username'] or 'ندارد'}</td></tr>"
        f"  <tr><th>📱 شماره تماس</th><td><code>{user['phone_number']}</code></td></tr>"
        f"  <tr><th>💳 کد ملی</th><td><code>{user['national_code']}</code></td></tr>"
        "</table>"
    )
    rich_msg = InputRichMessage(html=html_content)
    await callback.message.edit_text(text=None, reply_markup=inline.admin_verification_decision_keyboard(uid), rich_message=rich_msg)
    await callback.answer()

@router.callback_query(F.data.startswith("admin_verify_approve_"))
async def approve_verification_handler(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    uid = int(callback.data.split("_")[-1])
    await db.approve_verification(uid)
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_verifications")
    html_msg = (
        "<h1>🔐 درخواست احراز هویت</h1>"
        "<hr/>"
        "<h3>✅ احراز هویت کاربر با موفقیت تایید گردید.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ تایید شد!")
    
    try:
        html_msg = (
            f"<h1>🎉 احراز هویت شما تایید شد!</h1>"
            "<hr/>"
            f"<p>🎖 وضعیت حساب کاربری شما به وضعیت 🟢 <b>تایید شده (Verified)</b> ارتقا یافت.</p>"
            f"<br/>"
            f"<p>اکنون می‌توانید از تمامی خدمات ربات به صورت نامحدود استفاده کنید.</p>"
        )
        await bot.send_rich_message(
            chat_id=uid,
            rich_message=InputRichMessage(html=html_msg),
            message_effect_id="5046509860389126442"
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about verification approval: {e}")

@router.callback_query(F.data.startswith("admin_verify_reject_"))
async def reject_verification_handler(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    uid = int(callback.data.split("_")[-1])
    await state.update_data(reject_verify_uid=uid)
    await state.set_state(AdminReview.waiting_for_user_reject_reason)
    await callback.message.answer(
        "✍️ <b>علت رد درخواست احراز هویت را وارد کنید:</b>",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()

@router.message(AdminReview.waiting_for_user_reject_reason)
async def save_user_reject_reason(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
    data = await state.get_data()
    uid = data['reject_verify_uid']
    await state.clear()
    
    reason = message.text.strip()
    try: await message.react([ReactionTypeEmoji(emoji="👎")])
    except: pass
    await db.reject_verification(uid, reason)
    
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    await message.answer(
        f"❌ درخواست احراز هویت کاربر {uid} رد شد.",
        reply_markup=reply.client_main_menu(is_admin=is_admin)
    )
    
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="🔐 احراز هویت مجدد", callback_data="profile_start_verification")
        html_msg = (
            f"<h1>❌ درخواست احراز هویت شما رد شد</h1>"
            "<hr/>"
            f"<h3>⚠️ علت رد درخواست:</h3>"
            f"<blockquote>{reason}</blockquote>"
            f"<br/>"
            f"<p>لطفاً اطلاعات تصحیح شده و مدارک معتبر خود را مجدداً جهت بررسی ارسال کنید.</p>"
        )
        await bot.send_rich_message(
            chat_id=uid,
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup()
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about verification rejection: {e}")

@router.callback_query(F.data.startswith("admin_pending_projects"))
async def list_pending_projects(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    parts = callback.data.split("_")
    offset = int(parts[3]) if len(parts) > 3 else 0
    limit = 10
    
    total = await db.count_pending_projects()
    if total == 0:
        return await callback.message.edit_text(
            text=None,
            reply_markup=await get_admin_main_keyboard(),
            rich_message=InputRichMessage(html="📌 <b>هیچ پروژه در انتظار تایید وجود ندارد.</b>")
        )
        
    projects = await db.get_pending_projects_paginated(limit=limit, offset=offset)
    
    text = f"📌 <b>پروژه‌های در انتظار تایید:</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for p in projects:
        builder.button(
            text=f"📁 #{p['project_id']} — {p['title'][:30]}",
            callback_data=f"admin_view_proj_approve_{p['project_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_pending_projects_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_pending_projects_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت", callback_data="admin_back_to_panel")
    
    adjust_pattern = [1] * len(projects)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()

@router.callback_query(F.data.startswith("admin_view_proj_approve_"))
async def view_pending_project(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
        
    html_content = (
        f"<h1>📌 جزئیات پروژه در انتظار تایید</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>🆔 شماره پروژه</th><td>#{pid}</td></tr>"
        f"  <tr><th>👔 کارفرما ID</th><td><code>{project['client_id']}</code></td></tr>"
        f"  <tr><th>💰 بودجه پیشنهادی</th><td>{project['budget_min']:,} تا {project['budget_max']:,} تومان</td></tr>"
        f"  <tr><th>⏱ مهلت تحویل</th><td>{project['deadline_days']} روز</td></tr>"
        "</table>"
        "<br/>"
        "<h3>🏷 عنوان پروژه:</h3>"
        f"<blockquote>{project['title']}</blockquote>"
        "<br/>"
        "<h3>📋 توضیحات کامل پروژه:</h3>"
        f"<blockquote>{project['description']}</blockquote>"
    )
    rich_msg = InputRichMessage(html=html_content)
    await callback.message.edit_text(text=None, reply_markup=inline.admin_project_approval_decision_keyboard(pid), rich_message=rich_msg)
    await callback.answer()

@router.callback_query(F.data.startswith("admin_proj_approve_"))
async def approve_project_handler(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    project = await db.get_project(pid)
    if not project:
        return await callback.answer("پروژه یافت نشد.", show_alert=True)
    project = dict(project)
        
    await db.approve_project(pid)
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_projects")
    html_msg = (
        "<h1>📌 تایید پروژه</h1>"
        "<hr/>"
        "<h3>✅ پروژه با موفقیت تایید و منتشر شد.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ تایید شد!")
    
    # Notify Client
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💼 مدیریت پروژه", callback_data=f"client_project_{pid}_0")
        html_msg = (
            f"<h1>🎉 پروژه شما تایید و منتشر شد!</h1>"
            "<hr/>"
            f"<h3>📌 پروژه: {project['title']}</h3>"
            "<p>این پروژه هم‌اکنون برای تمامی فریلنسرها فعال و آماده دریافت پیشنهاد است.</p>"
            "<br/>"
            "<h3>📋 خلاصه مشخصات پروژه:</h3>"
            "<table bordered>"
            f"  <tr><th>💰 بودجه</th><td>{project['budget_min']:,} تا {project['budget_max']:,} تومان</td></tr>"
            f"  <tr><th>⏱ مهلت تحویل</th><td>{project['deadline_days']} روز</td></tr>"
            "</table>"
            "<br/>"
            "<h3>📄 توضیحات پروژه:</h3>"
            f"<blockquote>{project['description']}</blockquote>"
        )
        await bot.send_rich_message(
            chat_id=project['client_id'],
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup()
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about project approval: {e}")
        
    # Notify matching freelancers (Smart Matchmaking)
    try:
        matching_users = await db.get_matching_freelancers_for_project(project['title'], project['description'])
        if matching_users:
            import logging
            from aiogram.utils.keyboard import InlineKeyboardBuilder
            for user_id in matching_users:
                # Avoid notifying the client who posted the project
                if user_id == project['client_id']:
                    continue
                    
                builder_bid = InlineKeyboardBuilder()
                builder_bid.button(text="💬 ثبت پیشنهاد (بید)", callback_data=f"view_project_{pid}")
                
                alert_html = (
                    "<h1>🔔 پیشنهاد پروژه متناسب با تخصص شما!</h1>"
                    "<hr/>"
                    "<p>پروژه جدیدی مطابق با هشدارهای شغلی شما در ایکس‌لنسر منتشر شد:</p>"
                    "<br/>"
                    f"<h3>📌 {project['title']}</h3>"
                    "<br/>"
                    "<table bordered striped>"
                    f"  <tr><th>💰 بودجه</th><td>{project['budget_min']:,} تا {project['budget_max']:,} تومان</td></tr>"
                    f"  <tr><th>⏱ مهلت تحویل</th><td>{project['deadline_days']} روز</td></tr>"
                    "</table>"
                    "<br/>"
                    "<h3>📄 توضیحات پروژه:</h3>"
                    f"<blockquote>{project['description']}</blockquote>"
                )
                
                try:
                    await bot.send_rich_message(
                        chat_id=user_id,
                        rich_message=InputRichMessage(html=alert_html),
                        reply_markup=builder_bid.as_markup()
                    )
                except Exception as send_err:
                    logging.getLogger(__name__).error(f"Failed to send matchmaking alert to user {user_id}: {send_err}")
    except Exception as match_err:
        import logging
        logging.getLogger(__name__).error(f"Failed to perform project matchmaking for project #{pid}: {match_err}")
        
    # Broadcast to Telegram Channel with Submit Bid button
    try:
        bot_info = await bot.get_me()
        channel_id = await db.get_setting("channel_id", "@xlancer_jobs")
        if channel_id:
            from aiogram.utils.keyboard import InlineKeyboardBuilder
            builder_chan = InlineKeyboardBuilder()
            # Deep link to open the project in the bot
            channel_link = f"https://t.me/{bot_info.username}?start=project_{pid}"
            builder_chan.button(text="💬 ثبت پیشنهاد / مشاهده پروژه", url=channel_link)
            
            featured_badge = "⭐ #پروژه_ویژه\n" if project.get('is_featured') else ""
            category_name = project.get('category', '') or 'نامشخص'
            type_str = "تمام‌وقت/استخدامی" if project.get('project_type') == 'full_time' else "پروژه‌ای مقطعی"
            
            budget_min_str = f"{project['budget_min']:,}" if project['budget_min'] else "0"
            budget_max_str = f"{project['budget_max']:,}" if project['budget_max'] else "0"
            deadline_str = f"{project['deadline_days']} روز" if project['deadline_days'] else "بدون مهلت"
            
            channel_text = (
                f"📌 <b>پروژه جدید منتشر شد!</b>\n\n"
                f"{featured_badge}"
                f"🏷 <b>دسته‌بندی:</b> #{category_name.replace(' ', '_')}\n"
                f"💼 <b>نوع همکاری:</b> {type_str}\n"
                f"💰 <b>بودجه:</b> <b>{budget_min_str}</b> تا <b>{budget_max_str}</b> تومان\n"
                f"📅 <b>مهلت تحویل:</b> {deadline_str}\n\n"
                f"📝 <b>عنوان:</b> <b>{project['title']}</b>\n\n"
                f"📋 <b>توضیحات:</b>\n"
                f"<blockquote>{project['description']}</blockquote>\n\n"
                f"🚀 برای مشاهده جزئیات بیشتر و ثبت پیشنهاد خود، دکمه زیر را لمس کنید:"
            )
            
            if (channel_id.startswith('-') and channel_id[1:].isdigit()) or channel_id.isdigit():
                chat_id = int(channel_id)
            else:
                chat_id = channel_id
                
            await bot.send_message(
                chat_id=chat_id,
                text=channel_text,
                reply_markup=builder_chan.as_markup(),
                parse_mode="HTML"
            )
            logger.info(f"Successfully broadcasted project #{pid} to channel {channel_id}")
    except Exception as chan_err:
        logger.error(f"Failed to broadcast project #{pid} to channel: {chan_err}")
    
@router.callback_query(F.data.startswith("admin_proj_reject_"))
async def reject_project_handler(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    pid = int(callback.data.split("_")[-1])
    await state.update_data(reject_proj_id=pid)
    await state.set_state(AdminReview.waiting_for_proj_reject_reason)
    await callback.message.answer(
        "✍️ <b>علت رد پروژه را وارد کنید:</b>",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()

@router.message(AdminReview.waiting_for_proj_reject_reason)
async def save_proj_reject_reason(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
    data = await state.get_data()
    pid = data['reject_proj_id']
    await state.clear()
    
    reason = message.text.strip()
    try: await message.react([ReactionTypeEmoji(emoji="👎")])
    except: pass
    await db.reject_project(pid)
    
    project = await db.get_project(pid)
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    await message.answer(
        f"❌ پروژه #{pid} رد شد.",
        reply_markup=reply.client_main_menu(is_admin=is_admin)
    )
    
    if project:
        try:
            html_msg = (
                f"<h1>❌ پروژه شما رد شد</h1>"
                "<hr/>"
                f"<h3>📌 پروژه: {project['title']}</h3>"
                "<h3>⚠️ علت رد توسط مدیریت:</h3>"
                f"<blockquote>{reason}</blockquote>"
                "<br/>"
                "<h3>📋 خلاصه مشخصات پروژه:</h3>"
                "<table bordered>"
                f"  <tr><th>💰 بودجه</th><td>{project['budget_min']:,} تا {project['budget_max']:,} تومان</td></tr>"
                f"  <tr><th>⏱ مهلت تحویل</th><td>{project['deadline_days']} روز</td></tr>"
                "</table>"
                "<br/>"
                "<h3>📄 توضیحات پروژه:</h3>"
                f"<blockquote>{project['description']}</blockquote>"
                "<br/>"
                "<p>💡 می‌توانید وارد پنل کاربری شده، اطلاعات پروژه را ویرایش کنید تا برای بررسی مجدد ارسال شود.</p>"
            )
            await bot.send_rich_message(
                chat_id=project['client_id'],
                rich_message=InputRichMessage(html=html_msg)
            )
        except Exception as e:
            import logging
            logging.getLogger(__name__).error(f"Failed to notify user about project rejection: {e}")

@router.callback_query(F.data == "admin_pending_tickets")
async def admin_pending_tickets(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    open_tickets = await db.get_tickets_by_status('open')
    resolved_tickets = await db.get_tickets_by_status('resolved')
    
    from keyboards import inline
    html_msg = (
        "<h1>📞 تیکت‌های پشتیبانی کاربران</h1>"
        "<hr/>"
        "<p>لطفاً وضعیت تیکت‌های مورد نظر را جهت بررسی انتخاب کنید:</p>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_tickets_filter_keyboard(len(open_tickets), len(resolved_tickets)),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer()


@router.callback_query(F.data.startswith("admin_tickets_filter_"))
async def admin_tickets_filter(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    parts = callback.data.split("_")
    # Callback data is admin_tickets_filter_{status} or admin_tickets_filter_{status}_{offset}
    status = parts[3]
    offset = int(parts[4]) if len(parts) > 4 else 0
    limit = 10
    
    total = await db.count_tickets_by_status(status)
    status_label = "در انتظار پاسخ (باز)" if status == 'open' else "حل‌شده (بسته)"
    
    if total == 0:
        text = f"📞 هیچ تیکت پشتیبانی با وضعیت <b>{status_label}</b> وجود ندارد."
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="🔙 بازگشت به فیلترها", callback_data="admin_pending_tickets")
        await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
        await callback.answer()
        return
        
    tickets = await db.get_tickets_by_status_paginated(status, limit=limit, offset=offset)
        
    text = f"📞 <b>تیکت‌های پشتیبانی با وضعیت: {status_label}</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}\n\nبرای مشاهده یا پاسخ، روی تیکت کلیک کنید:"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for t in tickets:
        user = await db.get_user(t['user_id'])
        user_name = user['full_name'] or user['username'] or str(t['user_id']) if user else "نامشخص"
        builder.button(
            text=f"🎫 #SP-{t['ticket_id']} — {user_name}",
            callback_data=f"admin_view_ticket_{t['ticket_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_tickets_filter_{status}_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_tickets_filter_{status}_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت به فیلترها", callback_data="admin_pending_tickets")
    
    adjust_pattern = [1] * len(tickets)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()


@router.callback_query(F.data.startswith("admin_view_ticket_"))
async def admin_view_ticket(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    ticket_id = int(callback.data.split("_")[-1])
    ticket = await db.get_support_ticket(ticket_id)
    if not ticket:
        return await callback.answer("تیکت یافت نشد.", show_alert=True)
        
    user = await db.get_user(ticket['user_id'])
    user_name = user['full_name'] or user['username'] or str(ticket['user_id']) if user else "نامشخص"
    
    html_content = (
        f"<h1>🎫 تیکت پشتیبانی #SP-{ticket_id}</h1>"
        "<hr/>"
        "<table bordered>"
        f"  <tr><th>👤 فرستنده</th><td>{user_name} (ID: <code>{ticket['user_id']}</code>)</td></tr>"
        f"  <tr><th>📅 تاریخ</th><td>{to_shamsi(ticket['created_at'])}</td></tr>"
        f"  <tr><th>📊 وضعیت</th><td>{'باز 🟢' if ticket['status'] == 'open' else 'بسته 🔴'}</td></tr>"
        "</table>"
        "<br/>"
        "<h3>💬 متن پیام تیکت:</h3>"
        f"<blockquote>{ticket['message']}</blockquote>"
    )
    rich_msg = InputRichMessage(html=html_content)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    if ticket['status'] == 'open':
        builder.button(text="✍️ پاسخ به تیکت", callback_data=f"admin_ticket_reply_{ticket_id}", style="success")
        builder.button(text="❌ بستن تیکت", callback_data=f"admin_ticket_close_{ticket_id}", style="danger")
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_tickets", style="primary")
    builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=rich_msg)
    await callback.answer()

@router.callback_query(F.data.startswith("admin_ticket_reply_"))
async def admin_ticket_reply(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی غیرمجاز.", show_alert=True)
    
    ticket_id = int(callback.data.split("_")[-1])
    from states.forms import AdminSupportReply
    await state.update_data(reply_ticket_id=ticket_id)
    await state.set_state(AdminSupportReply.waiting_for_reply)
    await callback.message.answer(f"پاسخ خود را برای تیکت #SP-{ticket_id} بنویسید:", reply_markup=reply.cancel_menu())
    await callback.answer()

@router.callback_query(F.data.startswith("admin_ticket_close_"))
async def admin_ticket_close(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی غیرمجاز.", show_alert=True)
        
    ticket_id = int(callback.data.split("_")[-1])
    ticket = await db.get_support_ticket(ticket_id)
    if not ticket:
        return await callback.answer("تیکت یافت نشد.", show_alert=True)
        
    await db.close_support_ticket(ticket_id)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_tickets")
    html_msg = (
        "<h1>🎫 تیکت پشتیبانی</h1>"
        "<hr/>"
        "<h3>❌ تیکت با موفقیت بسته شد.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("تیکت بسته شد.")

@router.callback_query(F.data.startswith("admin_reply_"))
async def start_admin_reply(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی غیرمجاز.", show_alert=True)
    user_id = int(callback.data.split("_")[-1])
    from states.forms import AdminSupportReply
    await state.update_data(reply_to_user_id=user_id)
    await state.set_state(AdminSupportReply.waiting_for_reply)
    await callback.message.answer(f"پاسخ خود را برای کاربر {user_id} بنویسید:", reply_markup=reply.cancel_menu())
    await callback.answer()

@router.message(AdminSupportReply.waiting_for_reply)
async def send_admin_reply(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        return await state.clear()
    if message.text == texts.BTN_BACK:
        await state.clear()
        return await message.answer("لغو شد.", reply_markup=reply.client_main_menu(is_admin=True))
    data = await state.get_data()
    user_id = data.get("reply_to_user_id")
    ticket_id = data.get("reply_ticket_id")
    
    if not user_id and not ticket_id:
        return await state.clear()
        
    if ticket_id:
        ticket = await db.get_support_ticket(ticket_id)
        if ticket:
            user_id = ticket['user_id']
            
    if not user_id:
        return await state.clear()
        
    try:
        reply_text = message.text or message.caption or ""
        
        # Stream a partial rich message draft (Rich Message Drafts)
        import random
        import asyncio
        draft_id = random.randint(10000, 99999)
        draft_html = (
            f"<blockquote expandable><b>پیام شما (تیکت #SP-{ticket_id if ticket_id else ''}):</b>\n{ticket['message'] if ticket else ''}</blockquote>\n"
            f"👤 <b>پشتیبانی در حال نوشتن پاسخ است... ✍️</b>"
        )
        try:
            await bot.send_rich_message_draft(chat_id=user_id, draft_id=draft_id, rich_message=InputRichMessage(html=draft_html))
            await asyncio.sleep(1.2)
        except Exception:
            pass

        formatted_reply = (
            f"<blockquote expandable><b>پیام شما (تیکت #SP-{ticket_id if ticket_id else ''}):</b>\n{ticket['message'] if ticket else ''}</blockquote>\n"
            f"👤 <b>پاسخ پشتیبانی:</b>\n"
            f"\n"
            f"{reply_text}\n"
            f"\n"
            f"در صورت نیاز به ارتباط مجدد یا سوالات بیشتر دکمه زیر را کلیک کنید:"
        )
        try: await message.react([ReactionTypeEmoji(emoji="📨")])
        except: pass
        
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
        
        if message.text:
            await bot.send_message(user_id, formatted_reply, reply_markup=builder.as_markup(), parse_mode="HTML")
        else:
            await message.copy_to(user_id, caption=formatted_reply, reply_markup=builder.as_markup(), parse_mode="HTML")
        
        if ticket_id:
            await db.answer_support_ticket(ticket_id, reply_text)
            
        await message.answer("✅ پاسخ شما با موفقیت ارسال شد.", reply_markup=reply.client_main_menu(is_admin=True), message_effect_id="5107584321108051014")
    except Exception as e:
        await message.answer(f"❌ خطا در ارسال پیام به کاربر: {e}", reply_markup=reply.client_main_menu(is_admin=True))
    await state.clear()

@router.callback_query(F.data.startswith("admin_deposit_approve_"))
async def admin_deposit_approve_handler(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی غیرمجاز.", show_alert=True)
        
    deposit_id = int(callback.data.split("_")[-1])
    req = await db.get_deposit_request(deposit_id)
    if not req or req['status'] != 'pending':
        return await callback.answer("این درخواست قبلا بررسی شده یا وجود ندارد.", show_alert=True)
        
    await db.update_deposit_status(deposit_id, "approved")
    await db.update_balance(req['user_id'], req['amount'], "deposit", "شارژ کیف پول (تایید فیش بانکی)")
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_deposits")
    await callback.message.edit_caption(
        caption=callback.message.caption + "\n\n✅ <b>وضعیت: تایید شد.</b>",
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )
    await callback.answer("فیش تایید شد!")
    
    # Notify user
    try:
        user = await db.get_user(req['user_id'])
        role_back = "wallet_menu_back_freelancer" if user and 'role' in user.keys() and user['role'] == 'freelancer' else "wallet_menu_back"
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="💰 مشاهده کیف پول", callback_data=role_back)
        
        html_msg = (
            f"<h1>🎉 شارژ کیف پول با موفقیت انجام شد!</h1>"
            "<hr/>"
            f"<p>فیش واریزی ارسالی شما توسط مدیریت تایید و اعتبار آن به حساب شما افزوده شد.</p>"
            "<br/>"
            "<table bordered>"
            f"  <tr><th>💰 مبلغ شارژ شده</th><td>{req['amount']:,} تومان</td></tr>"
            "</table>"
            "<br/>"
            "<p>برای بررسی موجودی جدید خود، می‌توانید دکمه زیر را جهت ورود به منوی کیف پول کلیک کنید.</p>"
        )
        await bot.send_rich_message(
            chat_id=req['user_id'],
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup()
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about deposit approval: {e}")

@router.callback_query(F.data.startswith("admin_deposit_reject_"))
async def admin_deposit_reject_handler(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی غیرمجاز.", show_alert=True)
        
    deposit_id = int(callback.data.split("_")[-1])
    req = await db.get_deposit_request(deposit_id)
    if not req or req['status'] != 'pending':
        return await callback.answer("این درخواست قبلا بررسی شده یا وجود ندارد.", show_alert=True)
        
    await db.update_deposit_status(deposit_id, "rejected")
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_deposits")
    await callback.message.edit_caption(
        caption=callback.message.caption + "\n\n❌ <b>وضعیت: رد شد.</b>",
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )
    await callback.answer("فیش رد شد.")
    
    # Notify user
    try:
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="📞 ارتباط با پشتیبانی", callback_data="start_support_ticket")
        
        html_msg = (
            f"<h1>❌ فیش واریزی شما رد شد</h1>"
            "<hr/>"
            f"<p>فیش واریزی ارسالی شما به مبلغ <b>{req['amount']:,} تومان</b> متاسفانه مورد تایید مدیریت قرار نگرفت.</p>"
            "<br/>"
            "<p>در صورت نیاز به ثبت تیکت، پیگیری یا هرگونه سوال می‌توانید با کلیک بر روی دکمه زیر با پشتیبانی ما در ارتباط باشید.</p>"
        )
        await bot.send_rich_message(
            chat_id=req['user_id'],
            rich_message=InputRichMessage(html=html_msg),
            reply_markup=builder.as_markup()
        )
    except Exception as e:
        import logging
        logging.getLogger(__name__).error(f"Failed to notify user about deposit rejection: {e}")

@router.callback_query(F.data.startswith("admin_pending_deposits"))
async def list_pending_deposits(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    
    parts = callback.data.split("_")
    offset = int(parts[3]) if len(parts) > 3 else 0
    limit = 10
    
    total = await db.count_pending_deposits()
    if total == 0:
        text = "💳 هیچ فیش بانکی در انتظاری وجود ندارد."
        markup = await get_admin_main_keyboard()
        if callback.message.photo:
            await callback.message.delete()
            await callback.message.answer(text, reply_markup=markup)
        else:
            await callback.message.edit_text(text=None, reply_markup=markup, rich_message=InputRichMessage(html=text))
        await callback.answer()
        return
        
    deposits = await db.get_pending_deposits_paginated(limit=limit, offset=offset)
    
    text = f"💳 <b>فیش‌های واریزی در انتظار بررسی:</b>\n\nصفحه {offset // limit + 1} از {(total - 1) // limit + 1}\n\nبرای بررسی هر فیش روی آن کلیک کنید:"
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    for d in deposits:
        user = await db.get_user(d['user_id'])
        user_name = user['full_name'] or user['username'] or str(d['user_id']) if user else "نامشخص"
        builder.button(
            text=f"👤 {user_name} — {d['amount']:,}₸",
            callback_data=f"admin_view_deposit_{d['deposit_id']}"
        )
        
    nav_count = 0
    if offset > 0:
        builder.button(text="◀️ قبلی", callback_data=f"admin_pending_deposits_{offset - limit}")
        nav_count += 1
    if offset + limit < total:
        builder.button(text="بعدی ▶️", callback_data=f"admin_pending_deposits_{offset + limit}")
        nav_count += 1
        
    builder.button(text="🔙 بازگشت به پنل", callback_data="admin_back_to_panel")
    
    adjust_pattern = [1] * len(deposits)
    if nav_count == 2:
        adjust_pattern.append(2)
    elif nav_count == 1:
        adjust_pattern.append(1)
    adjust_pattern.append(1)
    
    builder.adjust(*adjust_pattern)
    
    markup = builder.as_markup()
    if callback.message.photo:
        await callback.message.delete()
        await callback.message.bot.send_rich_message(chat_id=callback.message.chat.id, rich_message=InputRichMessage(html=text), reply_markup=markup)
    else:
        await callback.message.edit_text(text=None, reply_markup=markup, rich_message=InputRichMessage(html=text))
    await callback.answer()

@router.callback_query(F.data.startswith("admin_view_deposit_"))
async def admin_view_deposit(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    deposit_id = int(callback.data.split("_")[-1])
    d = await db.get_deposit_request(deposit_id)
    if not d:
        return await callback.answer("درخواست یافت نشد.", show_alert=True)
        
    user = await db.get_user(d['user_id'])
    user_name = user['full_name'] or user['username'] or str(d['user_id']) if user else "نامشخص"
    
    text = (
        f"💳 <b>جزئیات فیش واریزی #{deposit_id}</b>\n\n"
        f"👤 کاربر: <b>{user_name}</b> (ID: `{d['user_id']}`)\n"
        f"💰 مبلغ: <b>{d['amount']:,} تومان</b>\n"
        f"📅 تاریخ درخواست: {to_shamsi(d['created_at'])}\n"
        f"📊 وضعیت: در انتظار بررسی\n"
    )
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="✅ تایید فیش و شارژ کیف پول", callback_data=f"admin_deposit_approve_{deposit_id}", style="success")
    builder.button(text="❌ رد فیش", callback_data=f"admin_deposit_reject_{deposit_id}", style="danger")
    builder.button(text="🔙 بازگشت به لیست", callback_data="admin_pending_deposits", style="primary")
    builder.adjust(1)
    
    await callback.message.delete()
    await callback.message.answer_photo(
        photo=d['photo_id'],
        caption=text,
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )
    await callback.answer()


# ── Admin Promo Codes Management ──────────────────────────────────────

@router.callback_query(F.data == "admin_promos")
async def admin_promos_list(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    promos = await db.get_all_promo_codes()
    text = "🎁 <b>مدیریت کدهای تخفیف و هدیه</b>\n\n"
    if not promos:
        text += "هیچ کد تخفیف فعالی وجود ندارد."
    else:
        text += "<b>لیست کدهای فعال:</b>\n\n"
        for p in promos:
            p_type_str = "شارژ کیف پول" if p['type'] == 'balance' else "اشتراک VIP"
            val_suffix = " تومان" if p['type'] == 'balance' else " ماه"
            uses_str = f"{p['uses']}/{p['max_uses']}" if p['max_uses'] else f"{p['uses']}/بی‌نهایت"
            text += f"• <code>{p['code']}</code> | {p_type_str}: <b>{p['value']:,}{val_suffix}</b> | استفاده: {uses_str}\n"
            
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="➕ ساخت کد هدیه جدید", callback_data="admin_promo_create_start", style="success")
    builder.button(text="🔙 بازگشت به پنل", callback_data="admin_back_to_panel", style="danger")
    builder.adjust(1)
    
    await callback.message.edit_text(text=None, reply_markup=builder.as_markup(), rich_message=InputRichMessage(html=text))
    await callback.answer()

@router.callback_query(F.data == "admin_promo_create_start")
async def admin_promo_create_start(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    await state.set_state(AdminPromoCreation.waiting_for_code)
    await callback.message.answer(
        "🎁 <b>ساخت کد هدیه جدید</b>\n\nلطفاً عبارت کد هدیه را وارد کنید (مثال: `NOROUZ1405`):",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()

@router.message(AdminPromoCreation.waiting_for_code)
async def admin_promo_create_code(message: Message, state: FSMContext):
    code = message.text.upper().strip()
    if len(code) < 3:
        return await message.answer("⚠️ کد هدیه باید حداقل ۳ کاراکتر باشد. مجدداً وارد کنید:")
        
    await state.update_data(code=code)
    await state.set_state(AdminPromoCreation.waiting_for_type)
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="💰 شارژ نقدی کیف پول (تومان)", callback_data="promo_type_balance")
    builder.button(text="🌟 اشتراک VIP رایگان (ماه)", callback_data="promo_type_vip")
    builder.adjust(1)
    
    await message.answer(
        f"کد هدیه: <code>{code}</code>\n\nلطفاً نوع پاداش کد هدیه را انتخاب کنید:",
        reply_markup=builder.as_markup(),
        parse_mode="HTML"
    )

@router.callback_query(AdminPromoCreation.waiting_for_type)
async def admin_promo_create_type(callback: CallbackQuery, state: FSMContext):
    p_type = callback.data.split("_")[-1]
    await state.update_data(type=p_type)
    await state.set_state(AdminPromoCreation.waiting_for_value)
    
    if p_type == 'balance':
        prompt = "💰 لطفاً مبلغ هدیه به **تومان** را وارد کنید (مثال: `50000`):"
    else:
        prompt = "🌟 لطفاً تعداد ماه‌های اشتراک VIP رایگان را وارد کنید (مثال: `1`):"
        
    await callback.message.edit_text(text=None, rich_message=InputRichMessage(html=prompt))
    await callback.answer()

@router.message(AdminPromoCreation.waiting_for_value)
async def admin_promo_create_value(message: Message, state: FSMContext):
    if not message.text.isdigit():
        return await message.answer("⚠️ لطفاً فقط عدد وارد کنید:")
        
    val = int(message.text)
    if val <= 0:
        return await message.answer("⚠️ مقدار باید بزرگتر از صفر باشد:")
        
    await state.update_data(value=val)
    await state.set_state(AdminPromoCreation.waiting_for_max_uses)
    
    from aiogram.utils.keyboard import ReplyKeyboardBuilder
    builder = ReplyKeyboardBuilder()
    builder.button(text="⏭ بدون محدودیت استفاده (بی‌نهایت)")
    builder.button(text=texts.BTN_BACK)
    builder.adjust(1)
    
    await message.answer(
        "👥 حداکثر تعداد دفعات استفاده از این کد توسط کاربران را وارد کنید (یا دکمه رد کردن را بزنید):",
        reply_markup=builder.as_markup(resize_keyboard=True),
        parse_mode="HTML"
    )

@router.message(AdminPromoCreation.waiting_for_max_uses)
async def admin_promo_create_max_uses(message: Message, state: FSMContext):
    max_uses = None
    if "بدون محدودیت" not in message.text and texts.BTN_BACK not in message.text:
        if not message.text.isdigit():
            return await message.answer("⚠️ لطفاً یک عدد معتبر وارد کنید یا دکمه رد کردن را بزنید:")
        max_uses = int(message.text)
        
    await state.update_data(max_uses=max_uses)
    await state.set_state(AdminPromoCreation.waiting_for_expiry)
    
    from aiogram.utils.keyboard import ReplyKeyboardBuilder
    builder = ReplyKeyboardBuilder()
    builder.button(text="⏭ مهلت پیش‌فرض (۳۰ روز)")
    builder.button(text=texts.BTN_BACK)
    builder.adjust(1)
    
    await message.answer(
        "📅 مهلت استفاده از کد هدیه را به **تعداد روز** وارد کنید (یا دکمه رد کردن را بزنید):",
        reply_markup=builder.as_markup(resize_keyboard=True),
        parse_mode="HTML"
    )

@router.message(AdminPromoCreation.waiting_for_expiry)
async def admin_promo_create_expiry(message: Message, state: FSMContext):
    expiry_days = 30
    if "مهلت پیش‌فرض" not in message.text and texts.BTN_BACK not in message.text:
        if not message.text.isdigit():
            return await message.answer("⚠️ لطفاً یک عدد معتبر برای روزها وارد کنید:")
        expiry_days = int(message.text)
        
    data = await state.get_data()
    await state.clear()
    
    await db.create_promo_code(
        code=data['code'],
        type=data['type'],
        value=data['value'],
        max_uses=data['max_uses'],
        expiry_days=expiry_days
    )
    
    await message.answer(
        f"✅ <b>کد هدیه با موفقیت ساخته شد!</b>\n\n"
        f"عبارت کد: <code>{data['code']}</code>\n"
        f"نوع: {'شارژ نقدی' if data['type'] == 'balance' else 'اشتراک VIP'}\n"
        f"مقدار: {data['value']:,}\n"
        f"حداکثر ظرفیت استفاده: {data['max_uses'] or 'بی‌نهایت'}\n"
        f"مهلت استفاده: {expiry_days} روز",
        reply_markup=reply.admin_main_menu(),
        parse_mode="HTML"
    )


@router.message(Command("addpromo"))
async def cmd_addpromo(message: Message, command: CommandObject):
    if message.from_user.id not in ADMIN_IDS: return
    
    if not command.args:
        return await message.answer("استفاده: /addpromo [code] [amount] [max_uses]")
        
    args = command.args.split()
    if len(args) != 3:
        return await message.answer("استفاده: /addpromo [code] [amount] [max_uses]")
        
    code, amount, max_uses = args[0].upper(), int(args[1]), int(args[2])
    success = await db.create_promo_code(code, amount, max_uses)
    
    if success:
        await message.answer(f"✅ کد تخفیف {code} با مبلغ {amount:,} تومان و {max_uses} بار ظرفیت ایجاد شد.")
    else:
        await message.answer("❌ خطا در ایجاد کد. شاید کد تکراری باشد.")

@router.callback_query(F.data.startswith("admin_svc_approve_"))
async def approve_service_handler(callback: CallbackQuery, bot: Bot):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    service_id = int(callback.data.split("_")[-1])
    svc = await db.get_service(service_id)
    if not svc:
        return await callback.answer("خدمت یافت نشد.", show_alert=True)
        
    await db.approve_service(service_id)
    
    html_msg = (
        "<h1>💻 تایید خدمت (سرویس) فریلنسر</h1>"
        "<hr/>"
        "<h3>✅ خدمت با موفقیت تایید و منتشر شد.</h3>"
    )
    await callback.message.edit_text(
        text=None,
        reply_markup=None,
        rich_message=InputRichMessage(html=html_msg)
    )
    await callback.answer("✅ تایید شد!")
    
    # Notify Freelancer
    try:
        await bot.send_message(
            svc['freelancer_id'],
            f"🎉 <b>خدمت شما تایید و منتشر شد!</b>\n\n"
            f"🛍 خدمت «{svc['title']}» تایید شد و هم‌اکنون در فروشگاه خدمات برای تمامی کارفرمایان قابل مشاهده و خرید است.",
            parse_mode="HTML"
        )
    except Exception as e:
        pass

@router.callback_query(F.data.startswith("admin_svc_reject_"))
async def reject_service_handler(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    service_id = int(callback.data.split("_")[-1])
    await state.update_data(reject_svc_id=service_id)
    await state.set_state(AdminReview.waiting_for_svc_reject_reason)
    await callback.message.answer(
        "✍️ <b>علت رد خدمت را وارد کنید:</b>",
        reply_markup=reply.cancel_menu(),
        parse_mode="HTML"
    )
    await callback.answer()

@router.message(AdminReview.waiting_for_svc_reject_reason)
async def save_svc_reject_reason(message: Message, state: FSMContext, bot: Bot):
    if not admin_only(message.from_user.id):
        await state.clear()
        return
    data = await state.get_data()
    service_id = data['reject_svc_id']
    await state.clear()
    
    reason = message.text.strip()
    try: await message.react([ReactionTypeEmoji(emoji="👎")])
    except: pass
    await db.reject_service(service_id)
    
    svc = await db.get_service(service_id)
    is_admin = message.from_user.id in __import__('config').ADMIN_IDS
    await message.answer(
        f"❌ خدمت #{service_id} رد شد.",
        reply_markup=reply.client_main_menu(is_admin=is_admin)
    )
    
    if svc:
        try:
            await bot.send_message(
                chat_id=svc['freelancer_id'],
                text=f"❌ <b>خدمت شما رد شد: {svc['title']}</b>\n\n<b>علت رد توسط مدیریت:</b>\n{reason}",
                parse_mode="HTML"
            )
        except Exception as e:
            import logging
            logging.getLogger(__name__).error(f"Failed to notify user about service rejection: {e}")


# ── Admin dynamic administrator management ──────────────────────────────

@router.callback_query(F.data == "admin_manage_admins")
async def admin_manage_admins_list(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
    await state.clear()
    
    admins_info = []
    for uid in ADMIN_IDS:
        user = await db.get_user(uid)
        if user:
            admins_info.append({
                'user_id': uid,
                'full_name': user['full_name'],
                'username': user['username']
            })
        else:
            admins_info.append({
                'user_id': uid,
                'full_name': "مدیر سیستم",
                'username': None
            })
            
    text = (
        "👥 <b>مدیریت مدیران (Admins)</b>\n\n"
        "در این بخش می‌توانید لیست مدیران فعلی ربات را مشاهده کرده، مدیر جدید اضافه کرده و یا مدیران تعریف‌شده را حذف کنید.\n\n"
        "⚠️ <b>توجه:</b> مدیران اصلی (تعریف شده در فایل <code>.env</code>) دارای نشان 👑 بوده و غیرقابل حذف می‌باشند."
    )
    
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_manage_admins_keyboard(admins_info, STATIC_ADMIN_IDS),
        rich_message=InputRichMessage(html=text)
    )
    await callback.answer()

@router.callback_query(F.data == "admin_static_explain")
async def admin_static_explain_handler(callback: CallbackQuery):
    await callback.answer(
        "🔒 این مدیر در تنظیمات اصلی سرور (.env) ثبت شده است و امکان حذف آن از طریق ربات وجود ندارد.",
        show_alert=True
    )

@router.callback_query(F.data.startswith("admin_view_admin_"))
async def admin_view_admin_handler(callback: CallbackQuery):
    target_uid = int(callback.data.replace("admin_view_admin_", ""))
    user = await db.get_user(target_uid)
    name = user['full_name'] if user else "کاربر ناشناس"
    username = f"@{user['username']}" if user and user['username'] else "بدون نام کاربری"
    role_type = "مدیر اصلی (ثابت)" if target_uid in STATIC_ADMIN_IDS else "مدیر پویا (قابل حذف)"
    
    alert_text = f"👤 نام: {name}\n🆔 شناسه: {target_uid}\n🌐 یوزرنیم: {username}\n🛡️ نوع: {role_type}"
    await callback.answer(alert_text, show_alert=True)

@router.callback_query(F.data == "admin_add_admin_start")
async def admin_add_admin_start_handler(callback: CallbackQuery, state: FSMContext):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    await state.set_state(AdminManageAdmins.waiting_for_new_admin_id)
    
    text = (
        "➕ <b>افزودن مدیر جدید</b>\n\n"
        "لطفاً شناسه عددی تلگرام (Telegram User ID) کاربر مورد نظر را ارسال کنید:\n\n"
        "💡 <i>نکته: کاربر باید قبلاً ربات را استارت کرده باشد.</i>"
    )
    
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    builder = InlineKeyboardBuilder()
    builder.button(text="🔙 انصراف", callback_data="admin_manage_admins")
    
    await callback.message.edit_text(
        text=None,
        reply_markup=builder.as_markup(),
        rich_message=InputRichMessage(html=text)
    )
    await callback.answer()

@router.message(AdminManageAdmins.waiting_for_new_admin_id)
async def process_add_admin_id(message: Message, state: FSMContext):
    if not admin_only(message.from_user.id):
        return
        
    val = message.text.strip()
    if not val.isdigit():
        from aiogram.utils.keyboard import InlineKeyboardBuilder
        builder = InlineKeyboardBuilder()
        builder.button(text="🔙 انصراف", callback_data="admin_manage_admins")
        
        return await message.bot.send_rich_message(
            chat_id=message.chat.id,
            rich_message=InputRichMessage(html="❌ <b>خطا:</b> شناسه وارد شده باید یک عدد صحیح (Telegram User ID) باشد. لطفاً مجدداً ارسال کنید یا روی دکمه انصراف کلیک کنید:"),
            reply_markup=builder.as_markup()
        )
        
    target_uid = int(val)
    
    if target_uid in ADMIN_IDS:
        return await message.bot.send_rich_message(
            chat_id=message.chat.id,
            rich_message=InputRichMessage(html=f"⚠️ <b>خطا:</b> کاربر با شناسه <code>{target_uid}</code> در حال حاضر در لیست مدیران قرار دارد.")
        )
        
    user = await db.get_user(target_uid)
    if not user:
        await db.create_user(target_uid, "new_admin", "مدیر سیستم")
        await db.set_user_role(target_uid, "admin")
        user = await db.get_user(target_uid)
    else:
        await db.set_user_role(target_uid, "admin")
        
    dynamic_admins_str = await db.get_setting("dynamic_admin_ids", "")
    dynamic_admin_ids = [int(x.strip()) for x in dynamic_admins_str.split(",") if x.strip()]
    if target_uid not in dynamic_admin_ids:
        dynamic_admin_ids.append(target_uid)
    new_dynamic_admins_str = ",".join(str(uid) for uid in dynamic_admin_ids)
    await db.update_setting("dynamic_admin_ids", new_dynamic_admins_str)
    
    if target_uid not in ADMIN_IDS:
        ADMIN_IDS.append(target_uid)
        
    await state.clear()
    
    name = user['full_name'] or "کاربر جدید"
    username = f" (@{user['username']})" if user['username'] else ""
    success_text = f"✅ <b>عملیات موفق</b>\n\nکاربر <b>{name}</b>{username} با شناسه <code>{target_uid}</code> با موفقیت به عنوان مدیر سیستم اضافه شد."
    
    admins_info = []
    for uid in ADMIN_IDS:
        u = await db.get_user(uid)
        if u:
            admins_info.append({
                'user_id': uid,
                'full_name': u['full_name'],
                'username': u['username']
            })
        else:
            admins_info.append({
                'user_id': uid,
                'full_name': "مدیر سیستم",
                'username': None
            })
            
    await message.bot.send_rich_message(
        chat_id=message.chat.id,
        rich_message=InputRichMessage(html=success_text)
    )
    
    list_text = (
        "👥 <b>مدیریت مدیران (Admins)</b>\n\n"
        "در این بخش می‌توانید لیست مدیران فعلی ربات را مشاهده کرده، مدیر جدید اضافه کرده و یا مدیران تعریف‌شده را حذف کنید.\n\n"
        "⚠️ <b>توجه:</b> مدیران اصلی (تعریف شده در فایل <code>.env</code>) دارای نشان 👑 بوده و غیرقابل حذف می‌باشند."
    )
    await message.bot.send_rich_message(
        chat_id=message.chat.id,
        rich_message=InputRichMessage(html=list_text),
        reply_markup=inline.admin_manage_admins_keyboard(admins_info, STATIC_ADMIN_IDS)
    )

@router.callback_query(F.data.startswith("admin_remove_admin_"))
async def admin_remove_admin_handler(callback: CallbackQuery):
    if not admin_only(callback.from_user.id):
        return await callback.answer("دسترسی ندارید.", show_alert=True)
        
    target_uid = int(callback.data.replace("admin_remove_admin_", ""))
    
    if target_uid in STATIC_ADMIN_IDS:
        return await callback.answer("❌ مدیران اصلی غیرقابل حذف هستند.", show_alert=True)
        
    dynamic_admins_str = await db.get_setting("dynamic_admin_ids", "")
    dynamic_admin_ids = [int(x.strip()) for x in dynamic_admins_str.split(",") if x.strip()]
    if target_uid in dynamic_admin_ids:
        dynamic_admin_ids.remove(target_uid)
    new_dynamic_admins_str = ",".join(str(uid) for uid in dynamic_admin_ids)
    await db.update_setting("dynamic_admin_ids", new_dynamic_admins_str)
    
    await db.set_user_role(target_uid, "user")
    
    if target_uid in ADMIN_IDS:
        ADMIN_IDS.remove(target_uid)
        
    await callback.answer("✅ مدیر با موفقیت حذف شد.", show_alert=True)
    
    admins_info = []
    for uid in ADMIN_IDS:
        u = await db.get_user(uid)
        if u:
            admins_info.append({
                'user_id': uid,
                'full_name': u['full_name'],
                'username': u['username']
            })
        else:
            admins_info.append({
                'user_id': uid,
                'full_name': "مدیر سیستم",
                'username': None
            })
            
    text = (
        "👥 <b>مدیریت مدیران (Admins)</b>\n\n"
        "در این بخش می‌توانید لیست مدیران فعلی ربات را مشاهده کرده، مدیر جدید اضافه کرده و یا مدیران تعریف‌شده را حذف کنید.\n\n"
        "⚠️ <b>توجه:</b> مدیران اصلی (تعریف شده در فایل <code>.env</code>) دارای نشان 👑 بوده و غیرقابل حذف می‌باشند."
    )
    
    await callback.message.edit_text(
        text=None,
        reply_markup=inline.admin_manage_admins_keyboard(admins_info, STATIC_ADMIN_IDS),
        rich_message=InputRichMessage(html=text)
    )
