import telebot
from telebot import types
import re, os

from config import BOT_TOKEN, ADMIN_ID, PROXY
from database import (init_db, add_user, increment_download, get_all_users,
                       get_stats, get_menu_buttons, add_menu_button, clear_menu_buttons)
from downloader import get_formats, download_video, download_best

# ---------- Proxy setup (برای دور زدن فیلترینگ) ----------
if PROXY:
    telebot.apihelper.proxy = {"http": PROXY, "https": PROXY}

bot = telebot.TeleBot(BOT_TOKEN)
init_db()

URL_REGEX = re.compile(r"(https?://\S+)")
INSTAGRAM_REGEX = re.compile(r"instagram\.com", re.IGNORECASE)
pending_urls = {}  # user_id -> url
broadcast_state = {}  # admin flow state
menu_edit_state = {}

GENERIC_ERROR = "اخ مشکل پیش امد لطفا چند لحظه دیگر امتحان کن"

def is_instagram(url):
    return bool(INSTAGRAM_REGEX.search(url))

# ---------- Keyboard builders ----------
def main_menu_kb():
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    for label in get_menu_buttons():
        kb.add(types.KeyboardButton(label))
    return kb

def quality_kb(url):
    kb = types.InlineKeyboardMarkup()
    for q in ["480", "720", "1080"]:
        kb.add(types.InlineKeyboardButton(f"{q}p", callback_data=f"q_{q}"))
    return kb

# ---------- User flow ----------
@bot.message_handler(commands=["start"])
def start(msg):
    user_name = msg.from_user.first_name or "دوست عزیز"
    add_user(msg.from_user.id, user_name)
    welcome_text = (
        f"سلام {user_name} 👋\n\n"
        "خوش اومدی به ربات دانلودرمون 🌹\n"
        "اینجا میتونید لینک های اینستاگرام/یوتیوب/تیکتاکتونو به ویدیو تبدیل کنید\n\n"
        "راستی فراموش نکنید مارو به بقیه هم معرفی کنید🫣"
    )
    bot.send_message(msg.chat.id, welcome_text, reply_markup=main_menu_kb())

@bot.message_handler(func=lambda m: URL_REGEX.search(m.text or ""))
def handle_link(msg):
    url = URL_REGEX.search(msg.text).group(1)
    user_id = msg.from_user.id
    add_user(user_id, msg.from_user.first_name)

    # Instagram: skip the quality picker, download best quality directly
    if is_instagram(url):
        wait_msg = bot.reply_to(msg, "در حال دانلود، لطفا صبر کن...")
        try:
            path = download_best(url, user_id)
            with open(path, "rb") as f:
                bot.send_video(msg.chat.id, f)
            increment_download(user_id)
            os.remove(path)
        except Exception:
            bot.send_message(msg.chat.id, GENERIC_ERROR)
        return

    # Other platforms (YouTube, TikTok): show quality picker
    try:
        info, heights = get_formats(url)
    except Exception:
        bot.reply_to(msg, GENERIC_ERROR)
        return

    pending_urls[user_id] = url
    bot.reply_to(msg, f"{info.get('title', 'Video')}\nSelect quality:",
                 reply_markup=quality_kb(url))

@bot.callback_query_handler(func=lambda c: c.data.startswith("q_"))
def handle_quality(call):
    user_id = call.from_user.id
    height = call.data.split("_")[1]
    url = pending_urls.get(user_id)
    if not url:
        bot.answer_callback_query(call.id, "Link expired, send it again.")
        return

    bot.answer_callback_query(call.id, "Downloading...")
    bot.edit_message_text("Downloading, please wait...", call.message.chat.id, call.message.message_id)
    try:
        path = download_video(url, height, user_id)
        with open(path, "rb") as f:
            bot.send_video(call.message.chat.id, f)
        increment_download(user_id)
        os.remove(path)
    except Exception:
        bot.send_message(call.message.chat.id, GENERIC_ERROR)

# ---------- Admin: Stats ----------
@bot.message_handler(commands=["stats"])
def stats(msg):
    if msg.from_user.id != ADMIN_ID:
        return
    total, logs = get_stats()
    text = f"تعداد کل کاربران: {total}\n\n"
    lines = []
    for uid, name, count in logs[:50]:
        display_name = name or "بدون نام"
        lines.append(f"{display_name} ({uid}): {count} دانلود")
    text += "\n".join(lines)
    bot.send_message(msg.chat.id, text or "اطلاعاتی موجود نیست.")

# ---------- Admin: Broadcast ----------
@bot.message_handler(commands=["broadcast"])
def broadcast_cmd(msg):
    if msg.from_user.id != ADMIN_ID:
        return
    broadcast_state[msg.from_user.id] = "awaiting_text"
    bot.send_message(msg.chat.id, "Send the message to broadcast.")

@bot.message_handler(commands=["poll"])
def poll_cmd(msg):
    if msg.from_user.id != ADMIN_ID:
        return
    broadcast_state[msg.from_user.id] = "awaiting_poll"
    bot.send_message(msg.chat.id, "Send poll as: Question | Option1 | Option2 | ...")

@bot.message_handler(func=lambda m: broadcast_state.get(m.from_user.id) == "awaiting_text")
def do_broadcast(msg):
    broadcast_state.pop(msg.from_user.id, None)
    users = get_all_users()
    sent = 0
    for uid in users:
        try:
            bot.send_message(uid, msg.text)
            sent += 1
        except Exception:
            pass
    bot.send_message(msg.chat.id, f"Broadcast sent to {sent} users.")

@bot.message_handler(func=lambda m: broadcast_state.get(m.from_user.id) == "awaiting_poll")
def do_poll(msg):
    broadcast_state.pop(msg.from_user.id, None)
    parts = [p.strip() for p in msg.text.split("|")]
    if len(parts) < 3:
        bot.send_message(msg.chat.id, "Format: Question | Option1 | Option2")
        return
    question, options = parts[0], parts[1:]
    users = get_all_users()
    sent = 0
    for uid in users:
        try:
            bot.send_poll(uid, question, options, is_anonymous=True)
            sent += 1
        except Exception:
            pass
    bot.send_message(msg.chat.id, f"Poll sent to {sent} users.")

# ---------- Admin: Menu customization ----------
@bot.message_handler(commands=["editmenu"])
def editmenu_cmd(msg):
    if msg.from_user.id != ADMIN_ID:
        return
    menu_edit_state[msg.from_user.id] = True
    bot.send_message(msg.chat.id,
        "Send new button labels separated by commas, e.g.: Help, About, Contact")

@bot.message_handler(func=lambda m: menu_edit_state.get(m.from_user.id))
def do_editmenu(msg):
    menu_edit_state.pop(msg.from_user.id, None)
    labels = [l.strip() for l in msg.text.split(",") if l.strip()]
    clear_menu_buttons()
    for label in labels:
        add_menu_button(label)
    bot.send_message(msg.chat.id, "Menu updated.", reply_markup=main_menu_kb())

if __name__ == "__main__":
    bot.infinity_polling()
