import json
import logging
import os
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from config import OWNERS
from db.database import conn, cursor
from services.user_service import get_all_users
from utils.custom_emoji import (
    TELEGRAM_CAPTION_LIMIT,
    parse_mode_for_custom_emoji_html,
    visible_text_length,
)

log = logging.getLogger("bot.broadcast")

DATA_JSON_PATH = "data/data.json"


def get_staff_user_ids():
    staff_ids = {int(user_id) for user_id in OWNERS}
    cursor.execute("SELECT id FROM admins")
    staff_ids.update(int(row["id"]) for row in cursor.fetchall())
    return staff_ids


def exclude_staff_targets(targets):
    staff_ids = get_staff_user_ids()
    filtered_targets = []

    for user_id in targets:
        if user_id is None:
            continue

        user_id = int(user_id)
        if user_id not in staff_ids:
            filtered_targets.append(user_id)

    return filtered_targets


def get_broadcast_targets():
    targets = set(get_all_users())
    if os.path.exists(DATA_JSON_PATH):
        with open(DATA_JSON_PATH, "r") as f:
            data = json.load(f)
        for item in data.get("link", []):
            if item.get("user_id"):
                targets.add(item["user_id"])
    return exclude_staff_targets(targets)


def get_approved_broadcast_targets():
    cursor.execute("SELECT DISTINCT user_id FROM transactions WHERE status = 'approved'")
    return exclude_staff_targets(row["user_id"] for row in cursor.fetchall())


def get_pending_broadcast_targets():
    targets = set()
    cursor.execute("SELECT DISTINCT user_id FROM pending_approvals")
    targets.update(row["user_id"] for row in cursor.fetchall())
    cursor.execute("SELECT DISTINCT user_id FROM transactions WHERE status = 'pending'")
    targets.update(row["user_id"] for row in cursor.fetchall())
    return exclude_staff_targets(targets)


def get_package_broadcast_targets(package_id):
    cursor.execute("SELECT nama FROM vip_packages WHERE id = ?", (int(package_id),))
    pkg = cursor.fetchone()
    if not pkg:
        return []

    package_name = pkg["nama"]
    targets = set()
    cursor.execute(
        """
        SELECT DISTINCT user_id
        FROM member_links
        WHERE status = 'Aktif' AND group_name LIKE ?
        """,
        (f"%{package_name}%",)
    )
    targets.update(row["user_id"] for row in cursor.fetchall())
    cursor.execute(
        """
        SELECT DISTINCT user_id
        FROM transactions
        WHERE status = 'approved' AND package_label LIKE ?
        """,
        (f"%{package_name}%",)
    )
    targets.update(row["user_id"] for row in cursor.fetchall())
    return exclude_staff_targets(targets)


def create_template(
    name,
    media_type,
    file_id,
    caption,
    button_text,
    button_url,
    created_by
):
    cursor.execute(
        """
        INSERT INTO broadcast_templates (
            name,
            media_type,
            file_id,
            caption,
            button_text,
            button_url,
            created_by
        )
        VALUES (?, ?, ?, ?, ?, ?, ?)
        """,
        (
            name,
            media_type,
            file_id,
            caption,
            button_text,
            button_url,
            created_by
        )
    )

    conn.commit()


def get_templates():
    cursor.execute("SELECT * FROM broadcast_templates")
    return cursor.fetchall()


def get_template(template_id):
    cursor.execute(
        "SELECT * FROM broadcast_templates WHERE id=?",
        (template_id,)
    )
    return cursor.fetchone()


def delete_template(template_id):
    cursor.execute(
        "DELETE FROM broadcast_templates WHERE id=?",
        (template_id,)
    )

    conn.commit()


def get_broadcast_targets_by_key(target_key, package_id=None):
    if target_key == "approved":
        return get_approved_broadcast_targets()
    if target_key == "pending":
        return get_pending_broadcast_targets()
    if target_key == "package":
        return get_package_broadcast_targets(package_id)
    return get_broadcast_targets()


async def send_template_message(context, template, user_id):
    (
        template_id,
        name,
        media_type,
        file_id,
        caption,
        button_text,
        button_url,
        created_by
    ) = template

    keyboard = None
    custom_emoji_parse_mode = parse_mode_for_custom_emoji_html(caption)
    caption_fits_media = visible_text_length(caption) <= TELEGRAM_CAPTION_LIMIT

    if button_text and button_url:
        keyboard = InlineKeyboardMarkup([[
            InlineKeyboardButton(button_text, url=button_url)
        ]])

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


async def send_broadcast(context, template, status_msg=None, chat_id=None, targets=None):

    users = exclude_staff_targets(targets) if targets is not None else get_broadcast_targets()
    total = len(users)
    log.info("[BROADCAST] Total target: %s user", total)

    success = 0
    failed = 0
    last_update = 0

    for i, user_id in enumerate(users, start=1):

        try:
            await send_template_message(context, template, user_id)
            success += 1

        except Exception as e:
            log.warning("[BROADCAST] Gagal kirim ke user_id=%s: %s", user_id, e)
            failed += 1

        if status_msg and i - last_update >= 5:
            last_update = i
            try:
                await status_msg.edit_text(
                    f"⏳ Mengirim broadcast... {success}/{total} berhasil"
                )
            except Exception:
                pass

    log.info("[BROADCAST] Selesai. Berhasil=%s Gagal=%s", success, failed)
    return success, failed
