import re

from telegram import (
    Update,
    InlineKeyboardButton,
    InlineKeyboardMarkup
)

from telegram.ext import ContextTypes

from services.auth_service import is_owner
from utils.custom_emoji import text_with_custom_emoji_html

from services.broadcast_service import (
    create_template,
    get_broadcast_targets_by_key,
    get_templates,
    get_template,
    delete_template,
    send_broadcast,
    send_template_message
)
from services.vip_service import get_all_packages, get_package_by_id


# =========================
# MENU BROADCAST
# =========================

BROADCAST_TARGET_LABELS = {
    "all": "Semua User",
    "approved": "Pembeli Approved",
    "pending": "Pending Payment",
}


def _target_label(target_key, package_id=None):
    if target_key == "package":
        pkg = get_package_by_id(package_id)
        return f"User Paket {pkg['nama']}" if pkg else "User Paket Tertentu"
    return BROADCAST_TARGET_LABELS.get(target_key, "Semua User")


def _target_count(target_key, package_id=None):
    return len(get_broadcast_targets_by_key(target_key, package_id))


async def _send_broadcast_preview(context, chat_id, template, reply_markup):
    (t_id, name, media_type, file_id, caption, button_text, button_url, created_by) = template
    preview_caption = f"👁️ <b>Preview: {name}</b>\n\n{caption}\n\n📣 Pilih target broadcast:"

    if media_type == "photo":
        await context.bot.send_photo(
            chat_id=chat_id,
            photo=file_id,
            caption=preview_caption,
            parse_mode="HTML",
            reply_markup=reply_markup
        )
    elif media_type == "video":
        await context.bot.send_video(
            chat_id=chat_id,
            video=file_id,
            caption=preview_caption,
            parse_mode="HTML",
            reply_markup=reply_markup
        )
    else:
        await context.bot.send_message(
            chat_id=chat_id,
            text=preview_caption,
            parse_mode="HTML",
            reply_markup=reply_markup
        )


def _target_selection_keyboard(template_id):
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("👥 Semua User", callback_data=f"broadcast_target_{template_id}_all")],
        [InlineKeyboardButton("✅ Pembeli Approved", callback_data=f"broadcast_target_{template_id}_approved")],
        [InlineKeyboardButton("⏳ Pending Payment", callback_data=f"broadcast_target_{template_id}_pending")],
        [InlineKeyboardButton("📦 User Paket Tertentu", callback_data=f"broadcast_target_pkg_{template_id}")],
        [InlineKeyboardButton("🧪 Test ke Saya", callback_data=f"broadcast_test_{template_id}")],
        [InlineKeyboardButton("❌ Batal", callback_data="broadcast_menu")]
    ])


def _confirm_keyboard(template_id, target_key, package_id=None):
    if target_key == "package":
        confirm_data = f"broadcast_confirm_pkg_{template_id}_{package_id}"
    else:
        confirm_data = f"broadcast_confirm_{template_id}_{target_key}"
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("✅ Kirim Sekarang", callback_data=confirm_data)],
        [InlineKeyboardButton("🧪 Test Kirim ke Saya", callback_data=f"broadcast_test_{template_id}")],
        [InlineKeyboardButton("❌ Batal", callback_data="broadcast_menu")]
    ])

async def open_broadcast_menu(update, context):

    query = update.callback_query

    templates = get_templates()

    keyboard = []

    # LIST TEMPLATE
    for item in templates:

        template_id = item[0]
        template_name = item[1]

        keyboard.append([
            InlineKeyboardButton(
                f"📣 {template_name}",
                callback_data=f"broadcast_send_{template_id}"
            )
        ])

    # TOMBOL TAMBAHAN
    keyboard.append([
        InlineKeyboardButton(
            "➕ Tambah Template",
            callback_data="broadcast_add"
        )
    ])

    # KHUSUS OWNER
    if is_owner(query.from_user.id):

        keyboard.append([
            InlineKeyboardButton(
                "🗑️ Hapus Template",
                callback_data="broadcast_delete"
            )
        ])

    keyboard.append([
        InlineKeyboardButton(
            "⬅️ Kembali",
            callback_data="panel_admin"
        )
    ])

    markup = InlineKeyboardMarkup(keyboard)

    # Jika pesan berisi media (foto/video), hapus dulu lalu kirim baru
    if query.message.photo or query.message.video:
        await query.message.delete()
        await context.bot.send_message(
            chat_id=query.from_user.id,
            text="📢 PANEL BROADCAST",
            reply_markup=markup
        )
    else:
        await query.edit_message_text(
            "📢 PANEL BROADCAST",
            reply_markup=markup
        )


# =========================
# HANDLE BUTTONS
# =========================

async def handle_broadcast_buttons(update, context):

    query = update.callback_query
    data = query.data

    # OPEN MENU
    if data == "broadcast_menu":
        await open_broadcast_menu(update, context)
        return

    # ADD TEMPLATE
    if data == "broadcast_add":

        context.user_data.clear()

        context.user_data["broadcast_step"] = "waiting_name"

        await query.edit_message_text(
            "📝 Masukan nama template"
        )

        return

    # DELETE MENU
    if data == "broadcast_delete":

        # HANYA OWNER
        if not is_owner(query.from_user.id):

            await query.answer(
                "❌ Hanya owner yang bisa menghapus template",
                show_alert=True
            )

            return

        templates = get_templates()

        keyboard = []

        for item in templates:

            keyboard.append([
                InlineKeyboardButton(
                    f"❌ {item[1]}",
                    callback_data=f"delete_template_{item[0]}"
                )
            ])

        keyboard.append([
            InlineKeyboardButton(
                "⬅️ Kembali",
                callback_data="broadcast_menu"
            )
        ])

        await query.edit_message_text(
            "🗑️ PILIH TEMPLATE",
            reply_markup=InlineKeyboardMarkup(keyboard)
        )

        return

    if data.startswith("delete_template_"):

        # HANYA OWNER
        if not is_owner(query.from_user.id):

            await query.answer(
                "❌ Hanya owner yang bisa menghapus template",
                show_alert=True
            )

            return

        template_id = int(data.split("_")[2])

        delete_template(template_id)

        await query.edit_message_text(
            "✅ Template berhasil dihapus"
        )

        await open_broadcast_menu(update, context)

        return

    # PREVIEW BROADCAST
    if data.startswith("broadcast_send_"):

        template_id = int(data.split("_")[2])
        template = get_template(template_id)

        if not template:
            await query.answer("❌ Template tidak ditemukan.", show_alert=True)
            return

        await query.message.delete()
        await _send_broadcast_preview(
            context,
            query.from_user.id,
            template,
            _target_selection_keyboard(template_id)
        )

        return

    if data.startswith("broadcast_target_pkg_"):

        template_id = int(data.replace("broadcast_target_pkg_", ""))
        packages = get_all_packages()
        if not packages:
            await query.answer("Belum ada paket VIP.", show_alert=True)
            return

        keyboard = []
        for pkg in packages:
            count = _target_count("package", pkg["id"])
            keyboard.append([
                InlineKeyboardButton(
                    f"📦 {pkg['nama']} ({count})",
                    callback_data=f"broadcast_targetpkg_{template_id}_{pkg['id']}"
                )
            ])
        keyboard.append([InlineKeyboardButton("⬅️ Kembali", callback_data=f"broadcast_send_{template_id}")])
        try:
            await query.message.delete()
        except Exception:
            await query.edit_message_reply_markup(reply_markup=None)
        await context.bot.send_message(
            chat_id=query.from_user.id,
            text="📦 <b>Pilih Paket Target</b>",
            parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(keyboard)
        )
        return

    if data.startswith("broadcast_targetpkg_"):

        _, _, template_id_str, package_id_str = data.split("_", 3)
        template_id = int(template_id_str)
        package_id = int(package_id_str)
        template = get_template(template_id)
        if not template:
            await query.answer("❌ Template tidak ditemukan.", show_alert=True)
            return

        label = _target_label("package", package_id)
        estimate = _target_count("package", package_id)
        await query.edit_message_text(
            "👁 <b>Preview Broadcast</b>\n\n"
            f"Template: <b>{template[1]}</b>\n"
            f"Target: <b>{label}</b>\n"
            f"Estimasi: <b>{estimate}</b> user",
            parse_mode="HTML",
            reply_markup=_confirm_keyboard(template_id, "package", package_id)
        )
        return

    if data.startswith("broadcast_target_"):

        _, _, template_id_str, target_key = data.split("_", 3)
        template_id = int(template_id_str)
        template = get_template(template_id)
        if not template:
            await query.answer("❌ Template tidak ditemukan.", show_alert=True)
            return

        label = _target_label(target_key)
        estimate = _target_count(target_key)
        try:
            await query.message.delete()
        except Exception:
            await query.edit_message_reply_markup(reply_markup=None)
        await context.bot.send_message(
            chat_id=query.from_user.id,
            text=(
                "👁 <b>Preview Broadcast</b>\n\n"
                f"Template: <b>{template[1]}</b>\n"
                f"Target: <b>{label}</b>\n"
                f"Estimasi: <b>{estimate}</b> user"
            ),
            parse_mode="HTML",
            reply_markup=_confirm_keyboard(template_id, target_key)
        )
        return

    if data.startswith("broadcast_test_"):

        template_id = int(data.replace("broadcast_test_", ""))
        template = get_template(template_id)
        if not template:
            await query.answer("❌ Template tidak ditemukan.", show_alert=True)
            return

        try:
            await send_template_message(context, template, query.from_user.id)
            await query.answer("✅ Test broadcast dikirim ke kamu.", show_alert=True)
        except Exception as e:
            await query.answer(f"⚠️ Test gagal: {e}", show_alert=True)
        return

    # KIRIM BROADCAST (setelah di konfirmasi)
    if data.startswith("broadcast_confirm_pkg_"):

        _, _, _, template_id_str, package_id_str = data.split("_", 4)
        template_id = int(template_id_str)
        package_id = int(package_id_str)
        template = get_template(template_id)
        targets = get_broadcast_targets_by_key("package", package_id)
        target_label = _target_label("package", package_id)

        await query.message.delete()
        status_msg = await context.bot.send_message(
            chat_id=query.from_user.id,
            text=f"⏳ Mengirim broadcast ke {target_label}..."
        )

        success, failed = await send_broadcast(
            context,
            template,
            status_msg=status_msg,
            chat_id=query.from_user.id,
            targets=targets
        )

        await context.bot.edit_message_text(
            chat_id=query.from_user.id,
            message_id=status_msg.message_id,
            text=(
                f"✅ Broadcast selesai\n\n"
                f"Target: {target_label}\n"
                f"Berhasil: {success}\n"
                f"Gagal: {failed}"
            )
        )
        return

    if data.startswith("broadcast_confirm_"):

        parts = data.split("_")
        template_id = int(parts[2])
        target_key = parts[3] if len(parts) > 3 else "all"
        template = get_template(template_id)
        targets = get_broadcast_targets_by_key(target_key)
        target_label = _target_label(target_key)

        # Hapus pesan preview (foto/video), lalu kirim status loading sebagai pesan baru
        await query.message.delete()
        status_msg = await context.bot.send_message(
            chat_id=query.from_user.id,
            text=f"⏳ Mengirim broadcast ke {target_label}..."
        )

        success, failed = await send_broadcast(
            context, template,
            status_msg=status_msg,
            chat_id=query.from_user.id,
            targets=targets
        )

        await context.bot.edit_message_text(
            chat_id=query.from_user.id,
            message_id=status_msg.message_id,
            text=(
                f"✅ Broadcast selesai\n\n"
                f"Target: {target_label}\n"
                f"Berhasil: {success}\n"
                f"Gagal: {failed}"
            )
        )

        return

    if data == "skip_button_text":

        context.user_data["button_text"] = None
        context.user_data["button_url"] = None

        create_template(
            name=context.user_data.get("template_name"),
            media_type=context.user_data.get("media_type"),
            file_id=context.user_data.get("file_id"),
            caption=context.user_data.get("caption"),
            button_text=None,
            button_url=None,
            created_by=query.from_user.id
        )

        context.user_data.clear()

        await query.edit_message_text(
            "✅ Template berhasil disimpan",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("⬅️ Kembali", callback_data="broadcast_menu")
            ]])
        )

        return

    if data == "skip_media":

        context.user_data["media_type"] = None
        context.user_data["file_id"] = None

        context.user_data["broadcast_step"] = "waiting_caption"

        await query.edit_message_text(
            "📝 Masukan caption\n\n"
            "Emoji premium bisa langsung ditempel di caption."
        )

        return


# =========================
# HANDLE MEDIA
# =========================

async def handle_broadcast_media(update: Update, context: ContextTypes.DEFAULT_TYPE):

    step = context.user_data.get("broadcast_step")

    if step != "waiting_media":
        return

    media_type = None
    file_id = None

    if update.message.photo:

        media_type = "photo"
        file_id = update.message.photo[-1].file_id

    elif update.message.video:

        media_type = "video"
        file_id = update.message.video.file_id

    else:
        return

    context.user_data["media_type"] = media_type
    context.user_data["file_id"] = file_id

    context.user_data["broadcast_step"] = "waiting_caption"

    await update.message.reply_text(
        "✅ Media berhasil disimpan\n\n"
        "Masukan caption. Emoji premium bisa langsung ditempel di caption."
    )


# =========================
# HANDLE TEXT
# =========================

async def handle_broadcast_text(update: Update, context: ContextTypes.DEFAULT_TYPE):

    user = update.effective_user

    step = context.user_data.get("broadcast_step")

    # TEMPLATE NAME
    if step == "waiting_name":

        context.user_data["template_name"] = update.message.text

        context.user_data["broadcast_step"] = "waiting_media"

        keyboard = [
            [
                InlineKeyboardButton(
                    "⏭️ Skip Media",
                    callback_data="skip_media"
                )
            ]
        ]

        await update.message.reply_text(
            "📸 Kirim photo/video atau skip",
            reply_markup=InlineKeyboardMarkup(keyboard)
        )

        return

    # CAPTION
    if step == "waiting_caption":

        caption = text_with_custom_emoji_html(update.message)

        # =========================
        # VALIDASI ADMIN
        # =========================

        if not is_owner(user.id):

            # DETEKSI LINK
            forbidden_link = re.search(
                r"(https?://|t\.me/)",
                caption
            )

            if forbidden_link:

                await update.message.reply_text(
                    "❌ Admin hanya boleh memasukan username telegram.\n\n"
                    "Contoh yang diperbolehkan:\n"
                    "@vip_channel"
                )

                return

        context.user_data["caption"] = caption

        context.user_data["broadcast_step"] = "waiting_button_text"

        keyboard = [
            [
                InlineKeyboardButton(
                    "⏭️ Skip",
                    callback_data="skip_button_text"
                )
            ]
        ]

        await update.message.reply_text(
            "🔘 Masukan teks tombol",
            reply_markup=InlineKeyboardMarkup(keyboard)
        )

        return

    # BUTTON TEXT
    if step == "waiting_button_text":

        context.user_data["button_text"] = update.message.text

        context.user_data["broadcast_step"] = "waiting_button_url"

        if is_owner(user.id):

            await update.message.reply_text(
                "🔗 Masukan username/link"
            )

        else:

            await update.message.reply_text(
                "👤 Masukan username telegram\n\ncontoh:\n@channel"
            )

        return

    # BUTTON URL
    if step == "waiting_button_url":

        button_url = update.message.text.strip()

        if not is_owner(user.id):
            valid = re.match(r"^@[A-Za-z0-9_]{5,}$", button_url)
            if not valid:
                await update.message.reply_text(
                    "❌ Admin hanya boleh menggunakan username telegram"
                )
                return
            button_url = f"https://t.me/{button_url.replace('@', '')}"
        elif button_url.startswith("@"):
            button_url = f"https://t.me/{button_url.replace('@', '')}"

        create_template(
            name=context.user_data.get("template_name"),
            media_type=context.user_data.get("media_type"),
            file_id=context.user_data.get("file_id"),
            caption=context.user_data.get("caption"),
            button_text=context.user_data.get("button_text"),
            button_url=button_url,
            created_by=user.id
        )

        context.user_data.clear()

        await update.message.reply_text(
            "✅ Template berhasil disimpan",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("⬅️ Kembali", callback_data="broadcast_menu")
            ]])
        )
