# handlers.py
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ContextTypes
from telegram.error import TelegramError
from config import ADMIN_ID, MAX_DAILY_UPLOADS, MESSAGES
from database import (
    upsert_user, log_stat, add_pending, get_setting,
    get_pending, delete_pending, user_daily_uploads,
    get_all_user_ids, add_sponsor_channel, get_sponsor_channels,
    remove_sponsor_channel
)
from utils import check_membership, join_keyboard, send_media_to_channel, format_user_name
from admin import handle_admin_actions
import logging
import asyncio

logger = logging.getLogger(__name__)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    await upsert_user(user)
    
    from config import get_main_keyboard
    is_admin = (user.id == ADMIN_ID)
    
    await update.message.reply_text(
        MESSAGES["start"],
        reply_markup=get_main_keyboard(is_admin),
    )

async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user = query.from_user
    data = query.data
    await query.answer()
    
    # پنل ادمین
    if user.id == ADMIN_ID and (data == "admin_panel" or data.startswith("admin_")):
        await handle_admin_actions(query, context, data)
        return
    
    # تایید/رد توسط ادمین
    if user.id == ADMIN_ID and (data.startswith("approve_") or data.startswith("reject_")):
        await handle_approval(query, context, data)
        return
    
    # ارسال موزیک
    if data in ("send_music", "send_anon"):
        ok, not_joined = await check_membership(context.bot, user.id)
        if not ok:
            context.user_data["pending_mode"] = data
            await query.edit_message_text(
                MESSAGES["join_required"] +
                "\n".join(f"🔹 {n}" for _, n in not_joined),
                reply_markup=join_keyboard(not_joined),
            )
            return
        context.user_data["mode"] = data
        msg = MESSAGES["send_anon"] if data == "send_anon" else MESSAGES["send_music"]
        await query.edit_message_text(msg)
    
    # بررسی مجدد عضویت
    if data == "check_joined":
        ok, not_joined = await check_membership(context.bot, user.id)
        if ok:
            mode = context.user_data.pop("pending_mode", "send_music")
            context.user_data["mode"] = mode
            msg = MESSAGES["waiting_after_join_anon"] if mode == "send_anon" else MESSAGES["waiting_after_join"]
            await query.edit_message_text(msg)
        else:
            await query.edit_message_text(
                MESSAGES["not_joined_retry"] +
                "\n".join(f"🔹 {n}" for _, n in not_joined),
                reply_markup=join_keyboard(not_joined),
            )

async def receive_music(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    message = update.message
    mode = context.user_data.get("mode")
    
    if user.id == ADMIN_ID and context.user_data.get("awaiting"):
        return
    
    count = await user_daily_uploads(user.id)
    if count >= MAX_DAILY_UPLOADS:
        await message.reply_text(MESSAGES["daily_limit"].format(MAX_DAILY_UPLOADS))
        return
    
    if mode not in ("send_music", "send_anon"):
        await message.reply_text(MESSAGES["send_start"])
        return
    
    ok, not_joined = await check_membership(context.bot, user.id)
    if not ok:
        context.user_data["pending_mode"] = mode
        context.user_data.pop("mode", None)
        await message.reply_text(
            MESSAGES["join_required"],
            reply_markup=join_keyboard(not_joined),
        )
        return
    
    is_voice = bool(message.voice)
    is_anon = (mode == "send_anon")
    
    if not (message.audio or message.voice):
        await message.reply_text(MESSAGES["only_audio"])
        return
    
    if message.audio:
        file_id = message.audio.file_id
        performer = message.audio.performer
        title = message.audio.title
        duration = message.audio.duration
    else:
        file_id = message.voice.file_id
        performer = None
        title = None
        duration = message.voice.duration
    
    context.user_data.pop("mode", None)
    require_approval = await get_setting("require_approval")
    
    if require_approval == "1":
        pending_id = await add_pending(
            user, file_id, performer, title, duration, is_voice, is_anon
        )
        await log_stat(user.id, "send_music" if not is_anon else "send_anon", f"pending:{pending_id}")
        
        sender_info = (
            f"👤 [{user.first_name}](tg://user?id={user.id})\n"
            f"🆔 `{user.id}`\n"
            f"📛 @{user.username}" if user.username else f"👤 [{user.first_name}](tg://user?id={user.id})\n🆔 `{user.id}`"
        )
        anon_label = "🕵️ ناشناس" if is_anon else "👤 با نام"
        track_info = f"{performer} — {title}" if performer and title else "🎵 فایل صوتی"
        
        approval_keyboard = InlineKeyboardMarkup([
            [
                InlineKeyboardButton(MESSAGES["btn_approve"], callback_data=f"approve_{pending_id}"),
                InlineKeyboardButton(MESSAGES["btn_reject"], callback_data=f"reject_{pending_id}"),
            ]
        ])
        
        try:
            if is_voice:
                await context.bot.send_voice(
                    chat_id=ADMIN_ID, voice=file_id,
                    caption=MESSAGES["admin_approval_caption_voice"].format(
                        title=MESSAGES["approval_request_title"],
                        sender_info=sender_info,
                        anon_label=anon_label,
                        pending_id=pending_id
                    ),
                    reply_markup=approval_keyboard,
                    parse_mode="Markdown",
                )
            else:
                await context.bot.send_audio(
                    chat_id=ADMIN_ID, audio=file_id,
                    caption=MESSAGES["admin_approval_caption"].format(
                        title=MESSAGES["approval_request_title"],
                        sender_info=sender_info,
                        anon_label=anon_label,
                        track_info=track_info,
                        pending_id=pending_id
                    ),
                    reply_markup=approval_keyboard,
                    parse_mode="Markdown",
                )
        except TelegramError as e:
            logger.error(f"خطا در ارسال به ادمین: {e}")
        
        await message.reply_text(MESSAGES["approval_required"])
    
    else:
        name_fmt = await get_setting("name_format")
        anon_tag = await get_setting("anonymous_hashtag")
        show_bot = await get_setting("show_bot_id")
        bot_user = await get_setting("bot_username")
        
        if is_anon:
            caption = anon_tag
        else:
            caption = MESSAGES["caption_normal"].format(format_user_name(user, name_fmt))
        
        if show_bot == "1" and bot_user:
            caption += MESSAGES["bot_signature"].format(bot_user)
        
        try:
            # ساخت row موقت برای send_media_to_channel
            temp_row = (
                None, user.id, user.first_name, user.username, file_id,
                performer, title, duration, is_voice, is_anon, None
            )
            await send_media_to_channel(context.bot, temp_row, caption)
            
            await log_stat(user.id, "send_music" if not is_anon else "send_anon", title or "")
            await message.reply_text("آهنگ رفت تو چنل✅\nدمت")
        except TelegramError as e:
            logger.error(f"خطا در ارسال به چنل: {e}")
            await message.reply_text(MESSAGES["send_failed"])

async def handle_approval(query, context, data: str):
    parts = data.split("_", 1)
    action = parts[0]
    pending_id = int(parts[1])
    
    row = await get_pending(pending_id)
    if not row:
        await query.edit_message_caption(MESSAGES["approval_not_found"])
        return
    
    user_id = row[1]
    first_name = row[2]
    is_anon = bool(row[9])
    
    if action == "approve":
        name_fmt = await get_setting("name_format")
        anon_tag = await get_setting("anonymous_hashtag")
        show_bot = await get_setting("show_bot_id")
        bot_user = await get_setting("bot_username")
        
        class FakeUser:
            def __init__(self):
                self.id = row[1]
                self.first_name = row[2]
                self.last_name = None
                self.username = row[3]
        
        if is_anon:
            caption = anon_tag
        else:
            caption = MESSAGES["caption_normal"].format(format_user_name(FakeUser(), name_fmt))
        
        if show_bot == "1" and bot_user:
            caption += MESSAGES["bot_signature"].format(bot_user)
        
        try:
            await send_media_to_channel(context.bot, row, caption)
            await log_stat(user_id, "send_music" if not is_anon else "send_anon", row[6] or "")
            await delete_pending(pending_id)
            
            await query.edit_message_caption(
                MESSAGES["approval_approved"] + f"\n\n👤 [{first_name}](tg://user?id={user_id})\n🎵 {row[5] or ''} — {row[6] or ''}",
                parse_mode="Markdown",
            )
            
            try:
                await context.bot.send_message(chat_id=user_id, text=MESSAGES["approved_user"])
            except TelegramError:
                pass
        except TelegramError as e:
            await query.edit_message_caption(f"❌ خطا در انتشار: {e}")
    
    elif action == "reject":
        await delete_pending(pending_id)
        await query.edit_message_caption(
            MESSAGES["approval_rejected"] + f"\n\n👤 [{first_name}](tg://user?id={user_id})",
            parse_mode="Markdown",
        )
        try:
            await context.bot.send_message(chat_id=user_id, text=MESSAGES["rejected_user"])
        except TelegramError:
            pass

# ============= پیام‌های ادمین (اسپانسر و برادکست) =============

async def admin_message_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """هندلر پیام‌های متنی ادمین (برای اضافه کردن اسپانسر و برادکست)"""
    user = update.effective_user
    awaiting = context.user_data.get("awaiting")
    
    # فقط ادمین
    if user.id != ADMIN_ID:
        return
    
    if not awaiting:
        return
    
    # ── اضافه کردن اسپانسر ──
    if awaiting == "add_sponsor" and update.message.text:
        channel_id = update.message.text.strip()
        if not (channel_id.startswith("@") or channel_id.lstrip("-").isdigit()):
            await update.message.reply_text(MESSAGES["invalid_channel"])
            return
        try:
            chat = await context.bot.get_chat(channel_id)
            name = chat.title or channel_id
            await add_sponsor_channel(channel_id, name)
            context.user_data.pop("awaiting", None)
            await update.message.reply_text(
                MESSAGES["channel_added"].format(name), parse_mode="Markdown"
            )
            # برگشت به پنل ادمین
            from admin import handle_admin_actions
            await handle_admin_actions(update, context, "admin_panel")
        except TelegramError:
            await update.message.reply_text(MESSAGES["channel_not_found"])
        return
    
    # ── پیام همگانی ──
    if awaiting == "broadcast":
        context.user_data.pop("awaiting", None)
        user_ids = await get_all_user_ids()
        success = 0
        fail = 0
        
        status_msg = await update.message.reply_text(
            MESSAGES["broadcast_progress"].format(len(user_ids))
        )
        
        for uid in user_ids:
            try:
                await update.message.copy_to(uid)
                success += 1
            except TelegramError:
                fail += 1
            await asyncio.sleep(0.05)
        
        await status_msg.edit_text(
            MESSAGES["broadcast_done"].format(success, fail),
            parse_mode="Markdown",
        )
        await log_stat(ADMIN_ID, "broadcast", f"success:{success} fail:{fail}")
        return