# translation.py version: 1.5
# script was programmed by:  Kodo
# For any inquiries:         @DevKodo
# Data source and operation: @SourceKodo

import asyncio
import aiohttp
import logging
import os
import shutil
import tempfile

from aiogram import Bot, Dispatcher, Router, F
from aiogram.types import (
    Message, CallbackQuery, FSInputFile,
    InlineKeyboardMarkup, InlineKeyboardButton,
)
from aiogram.filters import CommandStart, Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.memory import MemoryStorage
from sqlalchemy import select

import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))

from information.database import get_session, is_bot_paid as _is_paid_bot
from information.models import FactorySettings
from cobots.translation.db import (
    LANGUAGES,
    init_db, get_setting, set_setting, get_all_settings,
    get_enabled_languages, get_language_settings, toggle_language,
    get_or_create_user, get_user, get_all_active_users,
    get_statistics, ban_user, unban_user, get_banned_users,
    get_admins, is_admin, add_admin, remove_admin,
    get_mandatory_channels, add_mandatory_channel, remove_mandatory_channel,
    get_funded_channels, add_funded_channel, remove_funded_channel,
    record_funded_sub, get_funded_channel_count, mark_funded_complete,
    add_custom_button, get_custom_buttons, get_custom_button,
    update_custom_button, delete_custom_button,
)

logger = logging.getLogger(__name__)

BOT_TOKEN     = ""
BOT_USERNAME  = ""
MAKER_MSG     = "🤖 ادري عجبك البوت يلا اصنع واحد مثله مجاني !"
OWNER_ID      = 0
FACTORY_TOKEN = ""
_FACTORY_URL_CACHE: dict = {}   # توكن المصنع -> رابطه (يمنع تداخل الحقوق)

MAX_TEXT_LEN    = 5000
BROADCAST_BATCH = 30
BROADCAST_DELAY = 1.0

try:
    from cobots.ai.ai import GROQ_API_KEY as _GROQ_API_KEY, GROQ_API_URL as _GROQ_API_URL
except Exception:
    _GROQ_API_KEY = ""
    _GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"

_LLM_TRANSLATE_MODELS = [
    "openai/gpt-oss-20b",
    "allam-2-7b",
    "groq/compound-mini",
    "openai/gpt-oss-120b",
]

router     = Router()
dev_router = Router()


class UserStates(StatesGroup):
    waiting_lang_choice = State()


class DevStates(StatesGroup):
    waiting_broadcast     = State()
    waiting_broadcast_fwd = State()
    waiting_ban_id        = State()
    waiting_unban_id      = State()
    waiting_add_admin     = State()
    waiting_welcome       = State()
    waiting_closed_msg    = State()
    waiting_mand_fwd      = State()
    waiting_funded_fwd    = State()
    waiting_funded_count  = State()
    waiting_cbtn_label    = State()
    waiting_cbtn_content  = State()
    waiting_cbtn_edit_label   = State()
    waiting_cbtn_edit_content = State()
    waiting_cbtn_emoji        = State()
    waiting_cbtn_name         = State()
async def _build_dev_panel_text(bot_label: str) -> str:
    from information.database import get_bot_subscription
    from information.models import Bot as _BotModel
    from information.database import get_session as _get_session
    from sqlalchemy import select as _select

    text = (
        f"» <b>هذه هي لوحة التحكم وادارة {bot_label} الخاص بك</b>.\n\n"
        "» <b>لوحة تحكم متكاملة تتيح لك الإشراف على صلاحيات البوت، "
        "متابعة الإحصائيات الفورية وإدارة القنوات وكل شيء من مكان واحد</b>."
    )

    factory_url      = await get_main_factory_url()
    factory_username = factory_url.replace("https://t.me/", "") if factory_url else ""
    sub_deeplink     = f"https://t.me/{factory_username}?start=subscription" if factory_username else ""

    async with _get_session() as _sess:
        _res = await _sess.execute(
            _select(_BotModel).where(_BotModel.username.ilike(BOT_USERNAME), _BotModel.is_active == True)
        )
        _bot_rec = _res.scalar_one_or_none()

    if _bot_rec and _bot_rec.is_paid:
        _sub     = await get_bot_subscription(_bot_rec.id)
        _expires = _sub.expires_at.strftime("%d-%m-%Y") if _sub else "—"
        text += (
            f"\n» <b>البوت مدفوع حتى:</b> {_expires}"
            f"\n» يمكنك ادارة الاشتراك من هنا:"
            + (f'\n<a href="{sub_deeplink}">@{factory_username}</a>' if sub_deeplink else "")
        )
    elif _bot_rec and not _bot_rec.is_paid and sub_deeplink:
        text += (
            f"\n» اجعل بوتك مدفوعاً من هنا:"
            f'\n<a href="{sub_deeplink}">@{factory_username}</a>'
        )

    text += "\n\n» <b>قم بأختيار الاجراء المطلوب من القائمة ادناه</b>:"
    return text


async def is_owner_or_admin(user_id: int) -> bool:
    if user_id == OWNER_ID:
        return True
    return await is_admin(BOT_USERNAME, user_id)


async def notify_owner(bot: Bot, text: str):
    try:
        await bot.send_message(OWNER_ID, text, parse_mode="HTML", disable_web_page_preview=True)
    except Exception:
        pass


async def get_factory_maker_rights() -> bool:
    try:
        if await _is_paid_bot(BOT_USERNAME):
            return False
        async with get_session() as session:
            result   = await session.execute(select(FactorySettings).limit(1))
            settings = result.scalar_one_or_none()
            return settings.cobots_maker_rights if settings else False
    except Exception:
        return False


async def get_main_factory_url() -> str:
    if not FACTORY_TOKEN:
        return ""
    cached = _FACTORY_URL_CACHE.get(FACTORY_TOKEN)
    if cached:
        return cached
    try:
        import aiohttp
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f"https://api.telegram.org/bot{FACTORY_TOKEN}/getMe",
                timeout=aiohttp.ClientTimeout(total=10)
            ) as resp:
                data = await resp.json()
                if data.get("ok"):
                    url = f"https://t.me/{data['result']['username']}"
                    _FACTORY_URL_CACHE[FACTORY_TOKEN] = url
                    return url
    except Exception:
        pass
    return ""


_TRANSLATE_SEM = asyncio.Semaphore(2)


async def _translate_via_llm(text: str, target_lang: str, lang_name: str) -> str | None:
    if not _GROQ_API_KEY:
        return None
    headers = {"Authorization": f"Bearer {_GROQ_API_KEY}", "Content-Type": "application/json"}
    for model in _LLM_TRANSLATE_MODELS:
        payload = {
            "model": model,
            "messages": [
                {"role": "system", "content": (
                    "أنت مترجم محترف. ترجم النص إلى اللغة المحددة.\n"
                    "أخرج الترجمة فقط دون شرح أو مقدمة أو تنسيق إضافي، مع الحفاظ على معنى النص الأصلي وأسلوبه."
                )},
                {"role": "user", "content": f"اللغة المطلوبة: {lang_name} ({target_lang})\nالنص:\n{text}"},
            ],
            "temperature": 0.2,
            "max_tokens": 4096,
        }
        try:
            async with aiohttp.ClientSession() as sess:
                async with sess.post(
                    _GROQ_API_URL, headers=headers, json=payload,
                    timeout=aiohttp.ClientTimeout(total=90),
                ) as r:
                    if r.status == 200:
                        data = await r.json()
                        content = data["choices"][0]["message"]["content"]
                        if content and content.strip():
                            return content.strip()
                    else:
                        raw = await r.text()
                        logger.warning(f"Groq translation {r.status} (model={model}): {raw[:200]}")
        except Exception as e:
            logger.warning(f"LLM translation failed (model={model}): {e}")
    return None


async def do_translate(text: str, target_lang: str, lang_name: str = "") -> str:
    llm_result = await _translate_via_llm(text, target_lang, lang_name)
    if llm_result:
        return llm_result

    from deep_translator import GoogleTranslator
    from deep_translator import MyMemoryTranslator
    loop = asyncio.get_event_loop()
    async with _TRANSLATE_SEM:
        last_err = None
        for attempt in range(3):
            try:
                result = await loop.run_in_executor(
                    None,
                    lambda: GoogleTranslator(source="auto", target=target_lang).translate(text)
                )
                if result:
                    return result
            except Exception as e:
                last_err = e
                await asyncio.sleep(2 * (attempt + 1))
        try:
            result = await loop.run_in_executor(
                None,
                lambda: MyMemoryTranslator(source="auto", target=target_lang).translate(text)
            )
            if result:
                return result
        except Exception:
            pass
    if last_err:
        raise last_err
    return text


async def do_tts(text: str, lang: str, output_path: str) -> bool:
    try:
        from gtts import gTTS
        loop = asyncio.get_event_loop()
        tts_lang = lang.split("-")[0] if "-" in lang else lang
        await loop.run_in_executor(
            None,
            lambda: gTTS(text=text, lang=tts_lang, slow=False).save(output_path)
        )
        return True
    except Exception:
        return False


def kb_back() -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="رجوع", callback_data="tr:back", style="primary")]
    ])


async def kb_start() -> InlineKeyboardMarkup:
    rows = [[InlineKeyboardButton(text="طريقة الاستخدام", callback_data="tr:help", style="primary")]]
    try:
        for b in await get_custom_buttons(BOT_USERNAME):
            if not b.get("is_visible", 1):
                continue
            rows.append([_render_custom_button(b)])
    except Exception:
        pass
    return InlineKeyboardMarkup(inline_keyboard=rows)



def _entities_to_json(entities):
    import json as _json
    if not entities:
        return None
    return _json.dumps([
        {"type": e.type, "offset": e.offset, "length": e.length,
         "custom_emoji_id": getattr(e, "custom_emoji_id", None),
         "url": getattr(e, "url", None)}
        for e in entities
    ])


def _entities_from_json(s):
    import json as _json
    if not s:
        return None
    try:
        from aiogram.types import MessageEntity as _ME
        data = _json.loads(s)
        ents = []
        for d in data:
            kwargs = {"type": d["type"], "offset": d["offset"], "length": d["length"]}
            if d.get("custom_emoji_id"):
                kwargs["custom_emoji_id"] = d["custom_emoji_id"]
            if d.get("url"):
                kwargs["url"] = d["url"]
            ents.append(_ME(**kwargs))
        return ents
    except Exception:
        return None


def _has_custom_emoji(entities):
    if not entities:
        return False
    return any(getattr(e, "type", None) == "custom_emoji" for e in entities)


async def build_start_text(first_name: str, user_id: int):
    welcome = await get_setting(BOT_USERNAME, "welcome_message", "")
    ent_json = await get_setting(BOT_USERNAME, "welcome_message_entities", "")
    link    = f'<a href="tg://user?id={user_id}">{first_name}</a>'
    entities = _entities_from_json(ent_json)
    if welcome and _has_custom_emoji(entities):
        ph = "{first_name}"; idx = welcome.find(ph)
        text = welcome.replace(ph, first_name)
        if idx >= 0:
            shift = len(first_name) - len(ph)
            for e in entities:
                if e.offset > idx:
                    e.offset += shift
        return text, entities
    if welcome:
        text = welcome.replace("{first_name}", link)
    else:
        text = (
    f"<b>» أهلاً عزيزي: {link} 👋🏻</b>\n"
    "<b>» مرحباً بك في المنظومة الذكية المتخصصة في الترجمة الفورية والاحترافية.</b>\n\n"
    "<b>» يتميز البوت بدقة عالية في صياغة العبارات، حيث يدعم ترجمة أكثر من +60 لغة حول العالم.</b>\n"
    "<b>» لا يقتصر البوت على الترجمة النصية فقط، بل سيقوم تلقائياً بإرسال رسالة صوتية (Voice Note) لتبين لك النطق الصحيح للنص المترجم.</b>\n"
    "<b>» يمكنك ترجمة النصوص الطويلة والمحادثات بدقة وبأسرع وقت ممكن وبشكل مجاني بالكامل.</b>\n\n"
    "<b>» المنظومة جاهزة تماماً الآن 🌐:</b>\n"
    "<b>» كل ما عليك هو إرسال أي نص أو عبارة تريد ترجمتها ليبدأ البوت بالعمل فوراً.</b>"
        )
    if await get_factory_maker_rights():
        fac_url = await get_main_factory_url()
        if fac_url:
            fac_un = fac_url.replace("https://t.me/", "").replace("/", "")
            text += f'\n» <a href="{fac_url}">🤖 ادري عجبك البوت يلا اصنع واحد مثلة مجاني!</a>\n» @{fac_un}'

    return text, None


async def build_lang_keyboard() -> InlineKeyboardMarkup:
    enabled = set(await get_enabled_languages(BOT_USERNAME))
    rows    = []
    row     = []
    for lang_code, lang_name in LANGUAGES.items():
        if lang_code not in enabled:
            continue
        row.append(InlineKeyboardButton(text=lang_name, callback_data=f"tl:{lang_code}", style="success"))
        if len(row) == 3:
            rows.append(row)
            row = []
    if row:
        rows.append(row)
    rows.append([InlineKeyboardButton(text="رجوع", callback_data="tr:back", style="primary")])
    return InlineKeyboardMarkup(inline_keyboard=rows)


async def build_dev_panel_keyboard() -> InlineKeyboardMarkup:
    s       = await get_all_settings(BOT_USERNAME)
    is_open = "🟢 مفتوح" if s.get("is_open", "1") == "1" else "🔴 مقفول"
    n_blk   = "✅" if s.get("notify_blocked",   "1") == "1" else "✖️"
    n_new   = "✅" if s.get("notify_new_users",  "1") == "1" else "✖️"
    n_fund  = "✅" if s.get("fund_notify",       "1") == "1" else "✖️"
    return InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text=f"حالة البوت {is_open}",     callback_data="dev:toggle_open", style="success")],
        [
            InlineKeyboardButton(text=f"اشعار الحظر {n_blk}",   callback_data="dev:toggle_notify_blk", style="success"),
            InlineKeyboardButton(text=f"اشعار الدخول {n_new}",  callback_data="dev:toggle_notify_new", style="success"),
        ],
        [InlineKeyboardButton(text=f"اشعار الممولة {n_fund}",   callback_data="dev:toggle_notify_fund", style="success")],
        [
            InlineKeyboardButton(text="قسم الاذاعة",              callback_data="dev:broadcast", style="primary"),
            InlineKeyboardButton(text="قسم الاحصائيات",           callback_data="dev:stats", style="primary"),
        ],
        [
            InlineKeyboardButton(text="الاشتراك الاجباري",        callback_data="dev:mand", style="primary"),
            InlineKeyboardButton(text="قسم الادمنية",             callback_data="dev:admins", style="primary"),
        ],
        [InlineKeyboardButton(text="القنوات الممولة",             callback_data="dev:funded", style="danger")],
        [InlineKeyboardButton(text="تعديل رسالة الترحيب",         callback_data="dev:welcome", style="danger")],
        [InlineKeyboardButton(text="اللغات المدعومة",             callback_data="dev:langs", style="danger")],
        [
            InlineKeyboardButton(text="اضافة زر",     callback_data="cbtn:add", style="success"),
            InlineKeyboardButton(text="ادارة الازرار", callback_data="cbtn:manage", style="primary"),
        ],
    ])


async def build_dev_langs_keyboard() -> InlineKeyboardMarkup:
    lang_settings = await get_language_settings(BOT_USERNAME)
    items         = list(LANGUAGES.items())
    rows          = []
    for i in range(0, len(items), 3):
        row_items = items[i:i+3]
        row       = []
        for lang_code, lang_name in row_items:
            enabled = lang_settings.get(lang_code, {}).get("is_enabled", True)
            icon    = "✅" if enabled else "✖️"
            row.append(InlineKeyboardButton(
                text=f"{icon} {lang_name}",
                callback_data=f"devlang:{lang_code}", style="success"
            ))
        rows.append(row)
    rows.append([InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")])
    return InlineKeyboardMarkup(inline_keyboard=rows)


async def handle_subscription_check(bot: Bot, user_id: int, msg_or_cb) -> bool:
    is_cb      = isinstance(msg_or_cb, CallbackQuery)
    send       = msg_or_cb.message.answer if is_cb else msg_or_cb.answer
    channels   = await get_mandatory_channels(BOT_USERNAME)
    not_subbed = []
    for ch in channels:
        try:
            member = await asyncio.wait_for(bot.get_chat_member(int(ch["channel_id"]), user_id), timeout=5)
            if member.status in ("left", "kicked", "banned"):
                not_subbed.append(ch)
        except Exception:
            not_subbed.append(ch)
    if not_subbed:
        ch   = not_subbed[0]
        link = ch.get("invite_link") or (
            f"https://t.me/{ch['channel_username']}" if ch.get("channel_username") else None
        )
        if ch["display_type"] == "buttons":
            await send(
                "عزيزي المستخدم اشترك في القناة التالية قبل استخدام البوت:",
                reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                    [InlineKeyboardButton(
                        text=f"@{ch.get('channel_username') or ch['channel_title']}",
                        url=link or "#"
                    )],
                    [InlineKeyboardButton(text="✅ تحقق من الاشتراك", callback_data="tr:check_sub")],
                ])
            )
        else:
            msg = (
                f"عزيزي المستخدم اشترك في القناة التالية:\n"
                f"- <a href='{link}'>{ch['channel_title']}</a>\n\nاشترك ثم أرسل /start"
                if link else
                f"عزيزي المستخدم اشترك في القناة التالية:\n"
                f"- {ch['channel_title']}\n\nاشترك ثم أرسل /start"
            )
            await send(msg, parse_mode="HTML", disable_web_page_preview=True)
        return False
    funded = await get_funded_channels(BOT_USERNAME)
    for ch in funded:
        try:
            member = await asyncio.wait_for(bot.get_chat_member(int(ch["channel_id"]), user_id), timeout=5)
            if member.status not in ("left", "kicked", "banned"):
                await _record_funded(bot, user_id, ch)
        except Exception:
            pass
    return True


async def _record_funded(bot: Bot, user_id: int, ch: dict):
    added = await record_funded_sub(BOT_USERNAME, ch["id"], user_id)
    if not added:
        return
    current, target = await get_funded_channel_count(BOT_USERNAME, ch["id"])
    link = ch.get("invite_link") or (
        f"https://t.me/{ch['channel_username']}" if ch.get("channel_username")
        else str(ch["channel_id"])
    )
    notify = await get_setting(BOT_USERNAME, "fund_notify", "1")
    if notify == "1":
        await notify_owner(
            bot,
            f"🔔 <b>اشتراك جديد في قناة ممولة:</b>\n"
            f"المستخدم: <code>{user_id}</code>\n"
            f"القناة: <a href='{link}'>{ch['channel_title']}</a>\n"
            f"عدد المشتركين: <b>{current}/{target}</b>"
        )
    if current >= target:
        await mark_funded_complete(BOT_USERNAME, ch["id"])
        await notify_owner(
            bot,
            f"✅ <b>اكتملت قناة ممولة!</b>\n"
            f"القناة: <a href='{link}'>{ch['channel_title']}</a>\n"
            f"تم الوصول إلى <b>{target}</b> عضو."
        )

@router.message(CommandStart())
async def cmd_start(message: Message, state: FSMContext, bot: Bot):
    await state.clear()
    user   = message.from_user
    db_usr = await get_or_create_user(BOT_USERNAME, user.id, user.username, user.first_name)
    is_open = await get_setting(BOT_USERNAME, "is_open", "1")
    if db_usr.get("is_banned"):
        await message.answer("⛔ أنت محظور من استخدام هذا البوت.")
        return
    if is_open != "1" and not await is_owner_or_admin(user.id):
        msg = await get_setting(BOT_USERNAME, "closed_message", "🔴 البوت مقفول حالياً.")
        await message.answer(msg)
        return
    if not await handle_subscription_check(bot, user.id, message):
        return
    notify = await get_setting(BOT_USERNAME, "notify_new_users", "1")
    if notify == "1" and db_usr.get("is_new"):
        name = f"@{user.username}" if user.username else user.first_name
        await notify_owner(
            bot,
            f"👤 <b>مستخدم جديد!</b>\n"
            f"الاسم: {user.first_name}\nالمعرف: {name}\nالـ ID: <code>{user.id}</code>"
        )
    if await is_owner_or_admin(user.id):
        panel_text = await _build_dev_panel_text("بوت الترجمة")
        if await get_factory_maker_rights():
            panel_text += f"\n{MAKER_MSG}"
        await message.answer(panel_text, parse_mode="HTML", disable_web_page_preview=True, reply_markup=await build_dev_panel_keyboard())
    text, w_ents = await build_start_text(user.first_name, user.id)
    if w_ents:
        await message.answer(text, entities=w_ents, disable_web_page_preview=True, reply_markup=await kb_start())
    else:
        await message.answer(text, parse_mode="HTML", disable_web_page_preview=True, reply_markup=await kb_start())


@router.callback_query(F.data == "tr:check_sub")
async def cb_check_sub(callback: CallbackQuery, state: FSMContext, bot: Bot):
    if not await handle_subscription_check(bot, callback.from_user.id, callback):
        return
    await state.clear()
    text, w_ents = await build_start_text(callback.from_user.first_name, callback.from_user.id)
    if w_ents:
        await callback.message.edit_text(text, entities=w_ents, disable_web_page_preview=True, reply_markup=await kb_start())
    else:
        await callback.message.edit_text(text, parse_mode="HTML", disable_web_page_preview=True, reply_markup=await kb_start())
    await callback.answer()


@router.callback_query(F.data == "tr:back")
async def cb_back(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    text, w_ents = await build_start_text(callback.from_user.first_name, callback.from_user.id)
    if w_ents:
        await callback.message.edit_text(text, entities=w_ents, disable_web_page_preview=True, reply_markup=await kb_start())
    else:
        await callback.message.edit_text(text, parse_mode="HTML", disable_web_page_preview=True, reply_markup=await kb_start())
    await callback.answer()


@router.callback_query(F.data == "tr:help")
async def cb_help(callback: CallbackQuery):
    await callback.message.edit_text(
        "📖 <b>دليل ترجمة النصوص</b>\n\n"
        "✨ <b>كيفية الاستخدام:</b>\n\n"
        "1️⃣ أرسل أي نص تريد ترجمته\n"
        "2️⃣ اختر اللغة المطلوبة من القائمة\n"
        "3️⃣ استلم الترجمة فوراً مع صوت!\n\n"
        "🎯 <b>ميزات إضافية:</b>\n"
        "• ترجمة فورية بدقة عالية\n"
        "• دعم أكثر من 100 لغة\n"
        "• تشغيل صوتي للترجمة\n\n"
        "💡 <b>مثال:</b>\n"
        "أرسل: <code>Hello World</code>\n"
        "اختر: العربية\n"
        "النتيجة: مرحبا بالعالم + 🔊",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=kb_back()
    )
    await callback.answer()


@router.message(F.text & ~F.text.startswith("/"))
async def handle_text(message: Message, state: FSMContext, bot: Bot):
    user   = message.from_user
    db_usr = await get_or_create_user(BOT_USERNAME, user.id, user.username, user.first_name)
    is_open = await get_setting(BOT_USERNAME, "is_open", "1")
    if db_usr.get("is_banned"):
        await message.answer("⛔ أنت محظور من استخدام هذا البوت.")
        return
    if is_open != "1" and not await is_owner_or_admin(user.id):
        msg = await get_setting(BOT_USERNAME, "closed_message", "🔴 البوت مقفول حالياً.")
        await message.answer(msg)
        return
    if not await handle_subscription_check(bot, user.id, message):
        return

    text = message.text.strip()
    if len(text) > MAX_TEXT_LEN:
        await message.answer(
            f"⚠️ النص طويل جداً!\n"
            f"الحد الأقصى: <b>{MAX_TEXT_LEN:,}</b> حرف\n"
            f"نصك يحتوي على <b>{len(text):,}</b> حرف.\n\n"
            f"يرجى تقصير النص والمحاولة مجدداً.",
            parse_mode="HTML", disable_web_page_preview=True)
        return

    enabled = await get_enabled_languages(BOT_USERNAME)
    if not enabled:
        await message.answer("⚠️ لا توجد لغات مفعّلة حالياً. يرجى التواصل مع المشرف.")
        return

    await state.update_data(original_text=text)
    await state.set_state(UserStates.waiting_lang_choice)

    lang_kb = await build_lang_keyboard()
    await message.answer(
        "» <b>اختر اللغة التي تريد ترجمة النص اليها الان</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=lang_kb
    )

@router.callback_query(F.data.startswith("tl:"), UserStates.waiting_lang_choice)
async def cb_translate(callback: CallbackQuery, state: FSMContext, bot: Bot):
    lang_code = callback.data[3:]
    if lang_code not in LANGUAGES:
        await callback.answer("⚠️ لغة غير صالحة!", show_alert=True)
        return

    data          = await state.get_data()
    original_text = data.get("original_text", "")
    if not original_text:
        await state.clear()
        await callback.answer("⚠️ انتهت الجلسة. أرسل النص مجدداً.", show_alert=True)
        return

    lang_name = LANGUAGES[lang_code]
    await state.clear()
    await callback.message.edit_text("⏳ جاري الترجمة...")
    await callback.answer()

    uname   = BOT_USERNAME
    tok     = BOT_TOKEN
    chat_id = callback.message.chat.id
    msg_id  = callback.message.message_id

    async def _run_translate():
        b = Bot(token=tok)
        tmpdir = None
        try:
            try:
                translated = await do_translate(original_text, lang_code, lang_name)
            except Exception as e:
                logger.error(f"خطأ في الترجمة: {e}")
                await b.edit_message_text(
                    "❌ فشلت الترجمة. يرجى المحاولة مجدداً.",
                    chat_id=chat_id, message_id=msg_id,
                    reply_markup=kb_back())
                return

            orig_preview = original_text if len(original_text) <= 200 else original_text[:200] + "..."
            result_text  = (
                f"📝 <b>النص الأصلي:</b>\n"
                f"» <b>{orig_preview}</b>\n\n"
                f"🌐 <b>بعد الترجمة إلى {lang_name}:</b>\n"
                f"» <code>{translated}</code>"
            )

            if len(result_text) > 4096:
                result_text = (
                    f"📝 <b>النص الأصلي:</b>\n"
                    f"» <b>{orig_preview[:100]}</b>...\n\n"
                    f"🌐 <b>بعد الترجمة إلى {lang_name}:</b>\n"
                    f"» <code>{translated[:3500]}</code>"
                )

            await b.edit_message_text(result_text, chat_id=chat_id, message_id=msg_id, parse_mode="HTML", disable_web_page_preview=True, reply_markup=kb_back())

            tmpdir = tempfile.mkdtemp(prefix=f"tl_{chat_id}_")
            voice_path = os.path.join(tmpdir, "translation.mp3")
            tts_ok     = await do_tts(translated, lang_code, voice_path)
            if tts_ok and os.path.exists(voice_path):
                await b.send_voice(
                    chat_id,
                    FSInputFile(voice_path, filename="translation.mp3"),
                    caption=f"🔊 <b>ملف صوتي حسب اللغة المختارة ({lang_name})</b>", parse_mode="HTML",
                )
        except Exception as e:
            logger.warning(f"translation TTS فشل للغة {lang_code}: {e}")
        finally:
            if tmpdir:
                try:
                    shutil.rmtree(tmpdir, ignore_errors=True)
                except Exception:
                    pass
            await b.session.close()

    asyncio.create_task(_run_translate())


@router.callback_query(F.data.startswith("tl:"))
async def cb_translate_no_state(callback: CallbackQuery):
    await callback.answer("⚠️ أرسل النص أولاً ثم اختر اللغة.", show_alert=True)

@dev_router.callback_query(F.data == "dev:panel")
async def cb_dev_panel(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await callback.message.edit_text(
        "» <b>هذه هي لوحة التحكم وادارة بوت الترجمة الخاص بك</b>.\n\n» <b>لوحة تحكم متكاملة تتيح لك الإشراف على صلاحيات البوت، متابعة الإحصائيات وإدارة الاشتراكات وكل شيء من مكان واحد</b>.\n\n» <b>قم بأختيار الاجراء المطلوب من القائمة ادناه</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=await build_dev_panel_keyboard()
    )
    await callback.answer()


@dev_router.callback_query(F.data == "dev:toggle_open")
async def cb_toggle_open(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    current = await get_setting(BOT_USERNAME, "is_open", "1")
    await set_setting(BOT_USERNAME, "is_open", "0" if current == "1" else "1")
    await callback.answer("✅ تم التغيير.", show_alert=True)
    await callback.message.edit_reply_markup(reply_markup=await build_dev_panel_keyboard())


@dev_router.callback_query(F.data.in_({
    "dev:toggle_notify_blk", "dev:toggle_notify_new", "dev:toggle_notify_fund"
}))
async def cb_toggle_notify(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    key_map = {
        "dev:toggle_notify_blk":  "notify_blocked",
        "dev:toggle_notify_new":  "notify_new_users",
        "dev:toggle_notify_fund": "fund_notify",
    }
    key     = key_map[callback.data]
    current = await get_setting(BOT_USERNAME, key, "1")
    await set_setting(BOT_USERNAME, key, "0" if current == "1" else "1")
    await callback.answer("✅ تم التغيير.", show_alert=True)
    await callback.message.edit_reply_markup(reply_markup=await build_dev_panel_keyboard())


@dev_router.callback_query(F.data == "dev:stats")
async def cb_stats(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    stats   = await get_statistics(BOT_USERNAME)
    enabled = await get_enabled_languages(BOT_USERNAME)
    await callback.message.edit_text(
        f"📊 <b>إحصائيات البوت</b>\n\n"
        f"👥 إجمالي المستخدمين: <b>{stats['total']}</b>\n"
        f"✅ النشطون: <b>{stats['active']}</b>\n"
        f"🚫 المحظورون: <b>{stats['banned']}</b>\n"
        f"🔕 حظروا البوت: <b>{stats['blocked']}</b>\n\n"
        f"🌐 اللغات المفعّلة: <b>{len(enabled)}</b> / {len(LANGUAGES)}",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data == "dev:welcome")
async def cb_welcome(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.set_state(DevStates.waiting_welcome)
    await callback.message.edit_text(
        "» <b>قسم تعديل رسالة الترحيب</b>:\n\n» <b>استخدم</b> <code>{first_name}</code> <b>لعرض اسم المستخدم في رسالة الترحيب</b>.\n» <b>ارسل رسالة الترحيب الجديدة او ارسل كلمة 'حذف' لاعادة الرسالة الترحيبية حيثما كانت</b>:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_welcome)
async def process_welcome(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    text = message.text.strip() if message.text else ""
    is_reset = text.lower() in ("حذف", "delete", "reset")
    await set_setting(
        BOT_USERNAME, "welcome_message",
        "" if is_reset else text
    )
    await set_setting(BOT_USERNAME, "welcome_message_entities",
        "" if is_reset else (_entities_to_json(message.entities) or ""))
    await state.clear()
    await message.answer(
        "✅ تم تحديث رسالة الترحيب.",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="لوحة التحكم", callback_data="dev:panel", style="primary")]
        ])
    )

@dev_router.callback_query(F.data == "dev:langs")
async def cb_langs(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    enabled = await get_enabled_languages(BOT_USERNAME)
    await callback.message.edit_text(
        f"» <b>قسم اللغات المدعومة</b>:\n» <b>الغات المُفعلة {len(enabled)} من اصل {len(LANGUAGES)} لغة</b>.\n» <b>اضغط على أي زر من اللغات لتفعيلها أو ايقافها</b>:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=await build_dev_langs_keyboard()
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("devlang:"))
async def cb_toggle_lang(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    lang_code = callback.data[8:]
    if lang_code not in LANGUAGES:
        await callback.answer("⚠️ لغة غير صالحة!", show_alert=True); return
    await toggle_language(BOT_USERNAME, lang_code)
    lang_name = LANGUAGES[lang_code]
    enabled   = await get_enabled_languages(BOT_USERNAME)
    status    = "✅ مفعّلة" if lang_code in enabled else "✖️ موقوفة"
    await callback.answer(f"{lang_name}: {status}", show_alert=True)
    await callback.message.edit_reply_markup(reply_markup=await build_dev_langs_keyboard())

@dev_router.callback_query(F.data == "dev:broadcast")
async def cb_broadcast_menu(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await callback.message.edit_text(
        "» <b>قسم الاذاعة بالبوت:</b>.\n» <b>في هذا القسم تستطيع ان تقوم بعمل اذاعة من بوتك الى المستخدمين</b>.\n\n» <b>حدد نوع الاذاعة سواء رسالة موجهة او نصية</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="اذاعة نصية",  callback_data="bcast:text", style="success"),
                InlineKeyboardButton(text="اذاعة موجهة", callback_data="bcast:fwd", style="success"),
            ],
            [InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data == "bcast:text")
async def cb_bcast_text(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.set_state(DevStates.waiting_broadcast)
    await callback.message.edit_text(
        "» <b>ارسل رسالة الاذاعة المراد اذاعتها لجميع المستخدمين الان</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:broadcast", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data == "bcast:fwd")
async def cb_bcast_fwd(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.set_state(DevStates.waiting_broadcast_fwd)
    await callback.message.edit_text(
        "» <b>قم بتوجيه الرسالة المطلوب إذاعتها الان </b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:broadcast", style="primary")]
        ])
    )
    await callback.answer()


async def _do_broadcast(message: Message, wait: Message | None = None, forward: bool = False):
    uname   = BOT_USERNAME
    tok     = BOT_TOKEN
    chat_id = message.chat.id
    users  = await get_all_active_users(uname)
    sent   = failed = 0
    b = Bot(token=tok)
    try:
        for i, u in enumerate(users):
            try:
                if forward:
                    await b.forward_message(u["id"], from_chat_id=chat_id, message_id=message.message_id)
                elif message.text:
                    await b.send_message(u["id"], message.text, parse_mode="HTML", disable_web_page_preview=True)
                elif message.photo:
                    await b.send_photo(u["id"], message.photo[-1].file_id, caption=message.caption)
                elif message.video:
                    await b.send_video(u["id"], message.video.file_id, caption=message.caption)
                elif message.document:
                    await b.send_document(u["id"], message.document.file_id, caption=message.caption)
                elif message.voice:
                    await b.send_voice(u["id"], message.voice.file_id)
                elif message.audio:
                    await b.send_audio(u["id"], message.audio.file_id, caption=message.caption)
                elif message.sticker:
                    await b.send_sticker(u["id"], message.sticker.file_id)
                else:
                    await b.send_message(u["id"], "📢 إذاعة جديدة")
                sent += 1
            except Exception:
                failed += 1
            if (i + 1) % BROADCAST_BATCH == 0:
                await asyncio.sleep(BROADCAST_DELAY)
        if wait:
            await b.edit_message_text(
                chat_id=chat_id, message_id=wait.message_id,
                text=(f"» <b>تم ارسال الاذاعة الى كافة مستخدمين بوتك</b>.\n\n"
                      f"» <b>نجـح الارسال إلى: {sent} مستخدم</b>\n"
                      f"» <b>فشل الارسال إلى: {failed} مستخدم</b>"),
                parse_mode="HTML", disable_web_page_preview=True)
    except Exception:
        pass
    finally:
        await b.session.close()


@dev_router.message(DevStates.waiting_broadcast)
async def process_broadcast(message: Message, state: FSMContext, bot: Bot):
    await state.clear()
    wait = await message.answer("⏳ جاري إرسال الإذاعة...")
    asyncio.create_task(_do_broadcast(message, wait, forward=False))


@dev_router.message(DevStates.waiting_broadcast_fwd)
async def process_broadcast_fwd(message: Message, state: FSMContext, bot: Bot):
    await state.clear()
    wait = await message.answer("⏳ جاري إرسال الإذاعة...")
    asyncio.create_task(_do_broadcast(message, wait, forward=True))

@dev_router.callback_query(F.data == "dev:admins")
async def cb_admins(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    if callback.from_user.id != OWNER_ID:
        await callback.answer("⛔ للمالك فقط!", show_alert=True); return
    admins = await get_admins(BOT_USERNAME)
    text   = "» <b>عزيزي المطور هذا هو قسم التحكم بالادمنية</b>.\n» <b>يمكن اضافة وحذف الادمنية بالبوت من الازرار</b>:\n\n"
    for a in admins:
        name  = f"@{a['username']}" if a.get("username") else a.get("first_name", str(a["id"]))
        text += f"• {name} — <code>{a['id']}</code>\n"
    if not admins:
        text += "لا يوجد أدمنية حالياً."
    await callback.message.edit_text(
        text, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="اضافة ادمن", callback_data="dev:add_admin", style="success"),
                InlineKeyboardButton(text="حذف ادمن",   callback_data="dev:remove_admin", style="danger"),
            ],
            [InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data == "dev:add_admin")
async def cb_add_admin(callback: CallbackQuery, state: FSMContext):
    if callback.from_user.id != OWNER_ID:
        await callback.answer("⛔ للمالك فقط!", show_alert=True); return
    await state.set_state(DevStates.waiting_add_admin)
    await callback.message.edit_text(
        "» <b>أرسل أيدي المستخدم الذي تريد اضافته ادمن بالبوت</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:admins", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_add_admin)
async def process_add_admin(message: Message, state: FSMContext):
    if message.from_user.id != OWNER_ID: return
    try:
        target_id = int(message.text.strip())
    except (ValueError, AttributeError):
        await message.answer("⚠️ أرسل ID رقمي صحيح!"); return
    user = await get_user(BOT_USERNAME, target_id)
    if not user:
        await message.answer("⚠️ المستخدم غير موجود.")
        await state.clear(); return
    await add_admin(BOT_USERNAME, target_id, user.get("username"), user.get("first_name", ""))
    await state.clear()
    await message.answer(
        f"✅ تم تعيين <code>{target_id}</code> أدمناً بالبوت.", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="الأدمنية", callback_data="dev:admins", style="primary")]
        ])
    )


@dev_router.callback_query(F.data == "dev:remove_admin")
async def cb_remove_admin(callback: CallbackQuery):
    if callback.from_user.id != OWNER_ID:
        await callback.answer("⛔ للمالك فقط!", show_alert=True); return
    admins = await get_admins(BOT_USERNAME)
    if not admins:
        await callback.answer("لا يوجد أدمنية.", show_alert=True); return
    rows = [[InlineKeyboardButton(
        text=f"@{a['username']}" if a.get("username") else a.get("first_name", str(a["id"])),
        callback_data=f"dev:del_admin:{a['id']}", style="success"
    )] for a in admins]
    rows.append([InlineKeyboardButton(text="رجوع", callback_data="dev:admins")])
    await callback.message.edit_text(
        "» <b>اضغط على زر أي أدمن موجود لحذفه من قائمة الادمنية</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows)
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("dev:del_admin:"))
async def cb_del_admin(callback: CallbackQuery):
    if callback.from_user.id != OWNER_ID:
        await callback.answer("⛔ للمالك فقط!", show_alert=True); return
    await remove_admin(BOT_USERNAME, int(callback.data.split(":")[2]))
    await callback.answer("✅ تم إزالة الأدمن.", show_alert=True)
    await cb_admins(callback)


async def _show_mand_panel(callback: CallbackQuery):
    channels = await get_mandatory_channels(BOT_USERNAME)
    text     = "» <b>عزيزي المطور هذا هو قسم الاشتراك الاجباري</b>.\n» <b>يمكن اضافة وحذف القنوات من الازرار</b>:\n\n"
    rows     = []
    for ch in channels:
        name  = f"@{ch['channel_username']}" if ch.get("channel_username") else ch["channel_title"]
        text += f"• {name}\n"
        rows.append([InlineKeyboardButton(
            text=f"🗑 {name}", callback_data=f"dev:del_mand:{ch['id']}", style="danger"
        )])
    if not channels:
        text += "لا توجد قنوات."
    rows.append([InlineKeyboardButton(text="اضافة قناة", callback_data="dev:add_mand", style="success")])
    rows.append([InlineKeyboardButton(text="رجوع",           callback_data="dev:panel", style="primary")])
    await callback.message.edit_text(
        text, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows)
    )


@dev_router.callback_query(F.data == "dev:mand")
async def cb_mand(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await _show_mand_panel(callback); await callback.answer()


@dev_router.callback_query(F.data == "dev:add_mand")
async def cb_add_mand(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.update_data(mand_display_type="buttons")
    await callback.message.edit_text(
        "» <b>اختر الطريقة التي تريد عرض طلب الاشتراك فيها من المستخدم</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="ازرار",  callback_data="mand_dtype:buttons", style="success"),
                InlineKeyboardButton(text="رسالة نصية",  callback_data="mand_dtype:text", style="success"),
            ],
            [InlineKeyboardButton(text="رجوع", callback_data="dev:mand", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("mand_dtype:"))
async def cb_mand_dtype(callback: CallbackQuery, state: FSMContext):
    await state.update_data(mand_display_type=callback.data.split(":")[1])
    await state.set_state(DevStates.waiting_mand_fwd)
    await callback.message.edit_text(
        "» <b>ممتاز، الان قم بتوجيه رسالة من القناة/المجموعة لاضافتها</b>.\n⚠️ <b>يجب ان يكون البوت مشرفاً في القناة/المجموعة</b>.",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:mand", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_mand_fwd)
async def process_mand_fwd(message: Message, state: FSMContext, bot: Bot):
    if not await is_owner_or_admin(message.from_user.id): return
    if not message.forward_from_chat:
        await message.answer("⚠️ يرجى توجيه رسالة من القناة فقط!"); return
    chat    = message.forward_from_chat
    chat_id = chat.id
    try:
        member = await bot.get_chat_member(chat_id, (await bot.get_me()).id)
        if member.status not in ("administrator", "creator"):
            await message.answer("⚠️ يجب إضافة البوت كمشرف في القناة أولاً!")
            await state.clear(); return
    except Exception:
        await message.answer("⚠️ لا يمكن الوصول للقناة. تأكد أن البوت مشرف فيها!")
        await state.clear(); return
    invite_link = f"https://t.me/{chat.username}" if chat.username else None
    if not invite_link:
        try:
            link_obj    = await bot.create_chat_invite_link(chat_id)
            invite_link = link_obj.invite_link
        except Exception: pass
    data = await state.get_data()
    await add_mandatory_channel(
        BOT_USERNAME, str(chat_id), chat.title or str(chat_id),
        chat.username, invite_link, data.get("mand_display_type", "buttons")
    )
    await state.clear()
    await message.answer(
        f"✅ تمت إضافة القناة <b>{chat.title}</b>.", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="الاشتراك الإجباري", callback_data="dev:mand", style="primary")]
        ])
    )


@dev_router.callback_query(F.data.startswith("dev:del_mand:"))
async def cb_del_mand(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await remove_mandatory_channel(BOT_USERNAME, int(callback.data.split(":")[2]))
    await callback.answer("✅ تم حذف القناة.", show_alert=True)
    await _show_mand_panel(callback)

async def _show_funded_panel(callback: CallbackQuery):
    channels = await get_funded_channels(BOT_USERNAME)
    text     = "» <b>عزيزي المطور هذا هو قسم تمويل القنوات</b>.\n\n» <b>هذا القسم مختص في اجراء تمويل لقناة انت من يحددها حيث سيطلب البوت من المستخدمين الاشتراك في هذه القناة، عند اكتمال العدد المطلوب الذي تحدده انت سيتم ازالة القناة من القنوات الممولة</b>.\n\n"
    rows     = []
    for ch in channels:
        name  = f"@{ch['channel_username']}" if ch.get("channel_username") else ch["channel_title"]
        text += f"• {name} ({ch['current_count']}/{ch['target_count']})\n"
        rows.append([InlineKeyboardButton(
            text=f"🗑 {name}", callback_data=f"dev:del_funded:{ch['id']}", style="danger"
        )])
    if not channels:
        text += "لا توجد قنوات."
    rows.append([InlineKeyboardButton(text="اضافة قناة تمويل", callback_data="dev:add_funded", style="success")])
    rows.append([InlineKeyboardButton(text="رجوع",                 callback_data="dev:panel", style="primary")])
    await callback.message.edit_text(
        text, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows)
    )


@dev_router.callback_query(F.data == "dev:funded")
async def cb_funded(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await _show_funded_panel(callback); await callback.answer()


@dev_router.callback_query(F.data == "dev:add_funded")
async def cb_add_funded(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.update_data(funded_display_type="buttons")
    await callback.message.edit_text(
        "» <b>اختر الطريقة التي تريد عرض طلب الاشتراك فيها من المستخدم</b>:", parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="ازرار",  callback_data="funded_dtype:buttons", style="success"),
                InlineKeyboardButton(text="رسالة نصية",  callback_data="funded_dtype:text", style="success"),
            ],
            [InlineKeyboardButton(text="رجوع", callback_data="dev:funded", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("funded_dtype:"))
async def cb_funded_dtype(callback: CallbackQuery, state: FSMContext):
    await state.update_data(funded_display_type=callback.data.split(":")[1])
    await state.set_state(DevStates.waiting_funded_fwd)
    await callback.message.edit_text(
        "» <b>ممتاز، الان قم بتوجيه رسالة من القناة/المجموعة لاضافتها</b>.\n⚠️ <b>يجب ان يكون البوت مشرفاً في القناة/المجموعة</b>.",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:funded", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_funded_fwd)
async def process_funded_fwd(message: Message, state: FSMContext, bot: Bot):
    if not await is_owner_or_admin(message.from_user.id): return
    if not message.forward_from_chat:
        await message.answer("⚠️ يرجى توجيه رسالة من القناة فقط!"); return
    chat    = message.forward_from_chat
    chat_id = chat.id
    try:
        member = await bot.get_chat_member(chat_id, (await bot.get_me()).id)
        if member.status not in ("administrator", "creator"):
            await message.answer("⚠️ يجب إضافة البوت كمشرف في القناة أولاً!")
            await state.clear(); return
    except Exception:
        await message.answer("⚠️ لا يمكن الوصول للقناة. تأكد أن البوت مشرف فيها!")
        await state.clear(); return
    invite_link = f"https://t.me/{chat.username}" if chat.username else None
    if not invite_link:
        try:
            link_obj    = await bot.create_chat_invite_link(chat_id)
            invite_link = link_obj.invite_link
        except Exception: pass
    await state.update_data(
        funded_chat_id=str(chat_id), funded_title=chat.title or str(chat_id),
        funded_username=chat.username, funded_invite=invite_link,
    )
    await state.set_state(DevStates.waiting_funded_count)
    await message.answer(
        f"» <b>القناة</b>: {chat.title}\n» <b>قم بإرسال عدد المشتركين المستهدف الان</b>:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="dev:funded", style="primary")]
        ])
    )


@dev_router.message(DevStates.waiting_funded_count)
async def process_funded_count(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    try:
        target = int(message.text.strip())
        if target <= 0: raise ValueError
    except (ValueError, AttributeError):
        await message.answer("⚠️ أرسل رقماً صحيحاً أكبر من صفر!"); return
    data = await state.get_data()
    await add_funded_channel(
        BOT_USERNAME, data["funded_chat_id"], data["funded_title"],
        data.get("funded_username"), data.get("funded_invite"),
        data.get("funded_display_type", "buttons"), target,
    )
    await state.clear()
    await message.answer(
        f"» <b>تم اضافة القناة: {data['funded_title']} بنجاح</b>.\n» <b>الهدف: {target} عضو</b>",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="القنوات الممولة", callback_data="dev:funded", style="primary")]
        ])
    )


@dev_router.callback_query(F.data.startswith("dev:del_funded:"))
async def cb_del_funded(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await remove_funded_channel(BOT_USERNAME, int(callback.data.split(":")[2]))
    await callback.answer("✅ تم حذف القناة.", show_alert=True)
    await _show_funded_panel(callback)



def _render_custom_button(b: dict):
    label = b.get("label") or ""
    emoji = b.get("emoji")
    if emoji:
        label = f"{emoji} {label}"
    kwargs = {"text": label}
    if b["btn_type"] == "url":
        kwargs["url"] = b["content"]
    else:
        kwargs["callback_data"] = f"cbtn:press:{b['id']}"
    color = b.get("color")
    if color and color != "default":
        style_map = {"green": "success", "blue": "primary", "red": "danger"}
        tg = style_map.get(color)
        if tg:
            kwargs["style"] = tg
    if b.get("custom_emoji_id"):
        kwargs["icon_custom_emoji_id"] = b["custom_emoji_id"]
    return InlineKeyboardButton(**kwargs)


@dev_router.callback_query(F.data == "cbtn:add")
async def cbtn_add(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.clear()
    await callback.message.edit_text(
        "» قم بأختيار نوع الزر الذي سيظهر للمستخدم، يُمكن ان يكون رابط أو كالباك، اختر من الازرار:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="url - رابط",     callback_data="cbtn:type:url", style="success")],
            [InlineKeyboardButton(text="callback - كالباك", callback_data="cbtn:type:callback", style="success")],
            [InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("cbtn:type:"))
async def cbtn_type(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_type = callback.data.split(":")[2]
    await state.update_data(cbtn_type=btn_type)
    await state.set_state(DevStates.waiting_cbtn_label)
    await callback.message.edit_text(
        "» أرسل اسم الزر الذي سيظهر للمستخدم:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="cbtn:add", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_cbtn_label)
async def cbtn_process_label(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    if message.text and message.text.startswith("/"):
        await state.clear(); return
    label = (message.text or "").strip()
    if not label:
        await message.answer("⚠️ أرسل اسماً صحيحاً للزر!"); return
    data = await state.get_data()
    btn_type = data.get("cbtn_type")
    await state.update_data(cbtn_label=label)
    await state.set_state(DevStates.waiting_cbtn_content)
    prompt = "» أرسل الرابط الآن:" if btn_type == "url" else "» أرسل الرسالة النصية التي ستظهر عند الضغط على الزر:"
    await message.answer(
        prompt, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="cbtn:add", style="primary")]
        ])
    )


@dev_router.message(DevStates.waiting_cbtn_content)
async def cbtn_process_content(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    if message.text and message.text.startswith("/"):
        await state.clear(); return
    content = (message.text or "").strip()
    data = await state.get_data()
    btn_type = data.get("cbtn_type")
    label    = data.get("cbtn_label")
    if btn_type == "url":
        if not (content.startswith("http://") or content.startswith("https://") or content.startswith("tg://")):
            await message.answer("⚠️ أرسل رابطاً صحيحاً يبدأ بـ https:// أو http://")
            return
    if not content:
        await message.answer("⚠️ المحتوى فارغ!"); return
    await add_custom_button(BOT_USERNAME, btn_type, label, content)
    await state.clear()
    await message.answer(
        "✅ تمت إضافة الزر بنجاح، وسيظهر للمستخدمين الآن.",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text=" لوحة التحكم", callback_data="dev:panel", style="primary")]
        ])
    )


@dev_router.callback_query(F.data == "cbtn:manage")
async def cbtn_manage(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await state.clear()
    buttons = await get_custom_buttons(BOT_USERNAME)
    if not buttons:
        await callback.answer("لا توجد أزرار مضافة.", show_alert=True); return
    rows = [[InlineKeyboardButton(text=b["label"], callback_data=f"cbtn:view:{b['id']}", style="success")] for b in buttons]
    rows.append([InlineKeyboardButton(text="رجوع", callback_data="dev:panel", style="primary")])
    await callback.message.edit_text(
        "عزيزي المطور اختر الزر المراد ادارته:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows)
    )
    await callback.answer()


async def _cbtn_view_render(callback: CallbackQuery, btn_id: int):
    b = await get_custom_button(BOT_USERNAME, btn_id)
    if not b:
        await callback.answer("الزر غير موجود.", show_alert=True); return
    vis = "ظاهر ✅" if b.get("is_visible", 1) else "مخفي 🚫"
    await callback.message.edit_text(
        f"اسم الزر: <b>{b['label']}</b>\nالحالة: {vis}\n\n"
        "عزيزي المطور يمكنك ادارة الزر المضاف:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🗑 حذف الزر",        callback_data=f"cbtn:del:{btn_id}", style="danger")],
            [InlineKeyboardButton(text="✏️ تعديل محتوى الزر", callback_data=f"cbtn:edit:{btn_id}", style="success")],
            [InlineKeyboardButton(text="📝 تعديل اسم الزر",   callback_data=f"cbtn:ename:{btn_id}", style="success")],
            [InlineKeyboardButton(text="🎨 تعديل لون الزر",   callback_data=f"cbtn:ecolor:{btn_id}", style="success")],
            [InlineKeyboardButton(text="😀 تعديل ايموجي الزر", callback_data=f"cbtn:eemoji:{btn_id}", style="success")],
            [InlineKeyboardButton(text="👁 اخفاء/اظهار الزر",  callback_data=f"cbtn:toggle:{btn_id}", style="primary")],
            [InlineKeyboardButton(text="رجوع", callback_data="cbtn:manage", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("cbtn:view:"))
async def cbtn_view(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    await _cbtn_view_render(callback, int(callback.data.split(":")[2]))


@dev_router.callback_query(F.data.startswith("cbtn:del:"))
async def cbtn_del(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    await delete_custom_button(BOT_USERNAME, btn_id)
    await callback.answer("✅ تم حذف الزر.", show_alert=True)
    await cbtn_manage(callback, state)


@dev_router.callback_query(F.data.startswith("cbtn:toggle:"))
async def cbtn_toggle(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    b = await get_custom_button(BOT_USERNAME, btn_id)
    if not b:
        await callback.answer("الزر غير موجود.", show_alert=True); return
    new_vis = 0 if b.get("is_visible", 1) else 1
    await update_custom_button(BOT_USERNAME, btn_id, is_visible=new_vis)
    await callback.answer("✅ تم.", show_alert=False)
    await _cbtn_view_render(callback, btn_id)


@dev_router.callback_query(F.data.startswith("cbtn:ecolor:"))
async def cbtn_ecolor(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    await callback.message.edit_text(
        "🎨 اختر لون الزر:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🟢 أخضر", callback_data=f"cbtn:setcolor:{btn_id}:green", style="success"),
             InlineKeyboardButton(text="🔵 أزرق", callback_data=f"cbtn:setcolor:{btn_id}:blue", style="primary")],
            [InlineKeyboardButton(text="🔴 أحمر", callback_data=f"cbtn:setcolor:{btn_id}:red", style="danger"),
             InlineKeyboardButton(text="⚪ افتراضي", callback_data=f"cbtn:setcolor:{btn_id}:default")],
            [InlineKeyboardButton(text="رجوع", callback_data=f"cbtn:view:{btn_id}", style="primary")],
        ])
    )
    await callback.answer()


@dev_router.callback_query(F.data.startswith("cbtn:setcolor:"))
async def cbtn_setcolor(callback: CallbackQuery):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    parts  = callback.data.split(":")
    btn_id = int(parts[2]); color = parts[3]
    await update_custom_button(BOT_USERNAME, btn_id, color=color)
    await callback.answer("✅ تم تغيير اللون.", show_alert=False)
    await _cbtn_view_render(callback, btn_id)


@dev_router.callback_query(F.data.startswith("cbtn:eemoji:"))
async def cbtn_eemoji(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    await state.update_data(cbtn_emoji_id=btn_id)
    await state.set_state(DevStates.waiting_cbtn_emoji)
    await callback.message.edit_text(
        "😀 أرسل الإيموجي الجديد (عادي أو متحرك مميز)، أو أرسل <code>-</code> لحذف الإيموجي:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data=f"cbtn:view:{btn_id}", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_cbtn_emoji)
async def cbtn_process_emoji(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    if message.text and message.text.startswith("/"):
        await state.clear(); return
    data   = await state.get_data()
    btn_id = data.get("cbtn_emoji_id")
    text   = (message.text or "").strip()
    if text == "-":
        await update_custom_button(BOT_USERNAME, btn_id, emoji=None, custom_emoji_id=None)
        await state.clear()
        await message.answer("✅ تم حذف الإيموجي.", parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="ادارة الازرار", callback_data="cbtn:manage", style="primary")]]))
        return
    custom_emoji_id = None
    if message.entities:
        for e in message.entities:
            if e.type == "custom_emoji":
                custom_emoji_id = e.custom_emoji_id
                break
    if custom_emoji_id:
        await update_custom_button(BOT_USERNAME, btn_id, custom_emoji_id=custom_emoji_id, emoji=None)
        msg = "✅ تم تعيين الإيموجي المتحرك بنجاح!"
    else:
        await update_custom_button(BOT_USERNAME, btn_id, emoji=text, custom_emoji_id=None)
        msg = f"✅ تم تعيين الإيموجي: {text}"
    await state.clear()
    await message.answer(msg, parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="ادارة الازرار", callback_data="cbtn:manage", style="primary")]]))


@dev_router.callback_query(F.data.startswith("cbtn:ename:"))
async def cbtn_ename(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    await state.update_data(cbtn_ename_id=btn_id)
    await state.set_state(DevStates.waiting_cbtn_name)
    await callback.message.edit_text(
        "📝 أرسل الاسم الجديد للزر:",
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data=f"cbtn:view:{btn_id}", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_cbtn_name)
async def cbtn_process_name(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    if message.text and message.text.startswith("/"):
        await state.clear(); return
    label = (message.text or "").strip()
    if not label:
        await message.answer("⚠️ أرسل اسماً صحيحاً!"); return
    data   = await state.get_data()
    btn_id = data.get("cbtn_ename_id")
    await update_custom_button(BOT_USERNAME, btn_id, label=label)
    await state.clear()
    await message.answer("✅ تم تعديل اسم الزر.", parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="ادارة الازرار", callback_data="cbtn:manage", style="primary")]]))


@dev_router.callback_query(F.data.startswith("cbtn:edit:"))
async def cbtn_edit(callback: CallbackQuery, state: FSMContext):
    if not await is_owner_or_admin(callback.from_user.id):
        await callback.answer("⛔ غير مصرح!", show_alert=True); return
    btn_id = int(callback.data.split(":")[2])
    b = await get_custom_button(BOT_USERNAME, btn_id)
    if not b:
        await callback.answer("الزر غير موجود.", show_alert=True); return
    await state.update_data(cbtn_edit_id=btn_id, cbtn_edit_type=b["btn_type"])
    await state.set_state(DevStates.waiting_cbtn_edit_content)
    prompt = "» أرسل الرابط الجديد:" if b["btn_type"] == "url" else "» أرسل الرسالة النصية الجديدة:"
    await callback.message.edit_text(
        prompt, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data=f"cbtn:view:{btn_id}", style="primary")]
        ])
    )
    await callback.answer()


@dev_router.message(DevStates.waiting_cbtn_edit_content)
async def cbtn_process_edit_content(message: Message, state: FSMContext):
    if not await is_owner_or_admin(message.from_user.id): return
    if message.text and message.text.startswith("/"):
        await state.clear(); return
    content = (message.text or "").strip()
    data = await state.get_data()
    btn_type = data.get("cbtn_edit_type")
    btn_id   = data.get("cbtn_edit_id")
    if btn_type == "url" and not (content.startswith("http://") or content.startswith("https://") or content.startswith("tg://")):
        await message.answer("⚠️ أرسل رابطاً صحيحاً!"); return
    if not content:
        await message.answer("⚠️ المحتوى فارغ!"); return
    await update_custom_button(BOT_USERNAME, btn_id, content=content)
    await state.clear()
    await message.answer("✅ تم تعديل محتوى الزر بنجاح.", parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="ادارة الازرار", callback_data="cbtn:manage", style="primary")]]))


@router.callback_query(F.data.startswith("cbtn:press:"))
async def cbtn_press(callback: CallbackQuery):
    btn_id = int(callback.data.split(":")[2])
    b = await get_custom_button(BOT_USERNAME, btn_id)
    if not b:
        await callback.answer("هذا الزر لم يعد متاحاً.", show_alert=True); return
    await callback.message.edit_text(
        b["content"],
        parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="رجوع", callback_data="tr:back", style="primary")]
        ])
    )
    await callback.answer()


_translation_dispatcher: Dispatcher | None = None


def get_translation_dispatcher() -> Dispatcher:
    global _translation_dispatcher
    if _translation_dispatcher is None:
        storage                = MemoryStorage()
        _translation_dispatcher = Dispatcher(storage=storage)
        _translation_dispatcher.include_router(dev_router)
        _translation_dispatcher.include_router(router)
    return _translation_dispatcher
