import os
import re
from dotenv import load_dotenv
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    Application,
    CommandHandler,
    MessageHandler,
    CallbackQueryHandler,
    filters,
    ContextTypes,
)

import db
import downloader

load_dotenv()

TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
URL_PATTERN = re.compile(r"https?://\S+")


# ── Helpers ────────────────────────────────────────────────────────────────────

def _progress_bar(used: float, total: float, width: int = 10) -> str:
    if total <= 0:
        return "░" * width
    pct    = min(used / total, 1.0)
    filled = round(pct * width)
    return "█" * filled + "░" * (width - filled)


def _mb_display(mb: float) -> str:
    if mb >= 1024:
        return f"{mb / 1024:.1f}GB"
    return f"{round(mb, 1)}MB"


# ── Commands ───────────────────────────────────────────────────────────────────

async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    tg_user = update.effective_user
    is_new  = db.ensure_telegram_user(tg_user.id, tg_user.username, tg_user.first_name)
    quota   = db.get_user_quota(tg_user.id)

    bar           = _progress_bar(quota["storage_used_mb"], quota["storage_limit_mb"])
    limit_display = _mb_display(quota["storage_limit_mb"])

    if is_new:
        msg = (
            f"مرحباً {tg_user.first_name}! 👋\n"
            f"تم تسجيلك في نظام My Media.\n\n"
            f"🪪 رقمك التعريفي: `{tg_user.id}`\n"
            f"_(احتفظ بهذا الرقم لتواصل مع الدعم)_\n\n"
            f"📦 خطتك الحالية: {quota['plan_name']}\n"
            f"💾 التخزين: {bar} {_mb_display(quota['storage_used_mb'])} / {limit_display}\n\n"
            f"أرسل أي رابط لحفظه 📥\n"
            f"أو اكتب /help لعرض الأوامر"
        )
    else:
        msg = (
            f"أهلاً {tg_user.first_name}! 👋\n\n"
            f"🪪 رقمك: `{tg_user.id}`\n"
            f"📦 خطتك: {quota['plan_name']}\n"
            f"💾 التخزين: {bar} {_mb_display(quota['storage_used_mb'])} / {limit_display}\n\n"
            f"أرسل أي رابط لحفظه 📥"
        )

    await update.message.reply_text(msg, parse_mode='Markdown')


async def cmd_myid(update: Update, context: ContextTypes.DEFAULT_TYPE):
    tg_user = update.effective_user
    await update.message.reply_text(
        f"🪪 رقمك التعريفي:\n`{tg_user.id}`\n\n"
        f"أرسل هذا الرقم للدعم لترقية باقتك.",
        parse_mode='Markdown'
    )


async def cmd_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(
        "📋 *الأوامر المتاحة:*\n\n"
        "▫️ /start — تسجيل الدخول وعرض معلومات حسابك\n"
        "▫️ /myplan — عرض باقتك ومساحتك المستخدمة\n"
        "▫️ /myid — عرض رقمك التعريفي للتواصل مع الدعم\n"
        "▫️ /help — عرض هذه القائمة\n\n"
        "📥 *لحفظ محتوى:*\n"
        "أرسل أي رابط مباشرة وسيطلب منك البوت نوع الحفظ",
        parse_mode='Markdown'
    )


async def cmd_myplan(update: Update, context: ContextTypes.DEFAULT_TYPE):
    tg_user = update.effective_user
    db.ensure_telegram_user(tg_user.id, tg_user.username, tg_user.first_name)
    quota   = db.get_user_quota(tg_user.id)

    used  = quota["storage_used_mb"]
    limit = quota["storage_limit_mb"]
    bar   = _progress_bar(used, limit)
    pct   = round((used / limit * 100) if limit > 0 else 0, 1)

    file_line = (
        f"📁 الملفات: {quota['file_count']} / {quota['file_limit']}"
        if quota["file_limit"] else
        f"📁 الملفات: {quota['file_count']} (غير محدود)"
    )

    expires_line = (
        f"📅 تنتهي في: {str(quota['expires_at'])[:10]}"
        if quota["expires_at"] else
        "📅 الصلاحية: غير محدودة"
    )

    await update.message.reply_text(
        f"📊 معلومات اشتراكك:\n\n"
        f"• الخطة: {quota['plan_name']}\n"
        f"• التخزين: {bar} {pct}%\n"
        f"  {_mb_display(used)} / {_mb_display(limit)}\n"
        f"• {file_line}\n"
        f"• {expires_line}"
    )


# ── Message Handler ────────────────────────────────────────────────────────────

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    tg_user = update.effective_user
    db.ensure_telegram_user(tg_user.id, tg_user.username, tg_user.first_name)

    text = update.message.text.strip()

    if context.user_data.get("awaiting_description"):
        await process_save(update, context, description=text)
        return

    if not URL_PATTERN.match(text):
        await update.message.reply_text("أرسل رابطاً صحيحاً.")
        return

    existing = db.check_duplicate(text, tg_user.id)
    if existing:
        await update.message.reply_text("⚠️ هذا الرابط محفوظ مسبقاً.")
        return

    context.user_data["pending_url"] = text

    keyboard = InlineKeyboardMarkup([
        [
            InlineKeyboardButton("📥 حفظ ميديا", callback_data="save_media"),
            InlineKeyboardButton("🔗 رابط فقط",  callback_data="save_link"),
        ],
        [InlineKeyboardButton("❌ إلغاء", callback_data="cancel")],
    ])
    await update.message.reply_text("كيف تريد حفظ هذا الرابط؟", reply_markup=keyboard)


async def handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    action = query.data
    url    = context.user_data.get("pending_url")

    if action == "cancel" or not url:
        context.user_data.clear()
        await query.edit_message_text("تم الإلغاء.")
        return

    context.user_data["pending_action"]      = action
    context.user_data["awaiting_description"] = True

    await query.edit_message_text("✏️ اكتب مختصراً للرابط حتى تستطيع البحث عنه مستقبلاً:")


async def process_save(update: Update, context: ContextTypes.DEFAULT_TYPE, description: str):
    tg_user = update.effective_user
    tg_id   = tg_user.id

    url    = context.user_data.get("pending_url")
    action = context.user_data.get("pending_action")
    context.user_data.clear()

    if not url or not action:
        await update.message.reply_text("حدث خطأ. أرسل الرابط من جديد.")
        return

    if action == "save_link":
        ok, reason = db.can_upload(tg_id, file_size_mb=0.0)
        if not ok:
            await update.message.reply_text(reason)
            return
        link_id = db.save_link(url, "link", description, tg_id, 0.0)
        db.record_upload(tg_id, 0.0)
        await update.message.reply_text("✅ تم حفظ الرابط.")

    elif action == "save_media":
        msg = await update.message.reply_text("⏳ جاري التنزيل...")
        file_path = downloader.download(url)

        if file_path is None:
            keyboard = InlineKeyboardMarkup([[
                InlineKeyboardButton("🔗 حفظ كرابط", callback_data="save_link"),
                InlineKeyboardButton("❌ إلغاء",      callback_data="cancel"),
            ]])
            context.user_data["pending_url"]         = url
            context.user_data["pending_description"] = description
            await msg.edit_text("❌ فشل التنزيل. هل تريد حفظ الرابط فقط؟", reply_markup=keyboard)
            return

        # Check quota after download (use actual file size)
        try:
            file_size_mb = os.path.getsize(file_path) / (1024 * 1024)
        except OSError:
            file_size_mb = 0.0

        ok, reason = db.can_upload(tg_id, file_size_mb)
        if not ok:
            try:
                os.remove(file_path)
            except OSError:
                pass
            await msg.edit_text(reason)
            return

        link_id = db.save_link(url, "media", description, tg_id, file_size_mb)
        db.save_media(link_id, file_path)
        db.record_upload(tg_id, file_size_mb)

        quota = db.get_user_quota(tg_id)
        used  = quota["storage_used_mb"]
        limit = quota["storage_limit_mb"]

        # Warn at 80%
        pct = (used / limit * 100) if limit > 0 else 0
        extra = ""
        if pct >= 80:
            extra = f"\n\n⚠️ تنبيه: استخدمت {round(pct)}% من مساحتك!"

        await msg.edit_text(f"✅ تم الحفظ.{extra}")


async def handle_fallback_save_link(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handles 'save_link' after a failed download (description already saved)."""
    query = update.callback_query
    await query.answer()

    if query.data == "cancel":
        context.user_data.clear()
        await query.edit_message_text("تم الإلغاء.")
        return

    tg_id       = update.effective_user.id
    url         = context.user_data.get("pending_url")
    description = context.user_data.get("pending_description")
    context.user_data.clear()

    if url:
        ok, reason = db.can_upload(tg_id, 0.0)
        if not ok:
            await query.edit_message_text(reason)
            return
        db.save_link(url, "link", description, tg_id, 0.0)
        db.record_upload(tg_id, 0.0)
        await query.edit_message_text("✅ تم حفظ الرابط.")


# ── Main ──────────────────────────────────────────────────────────────────────

def main():
    app = Application.builder().token(TOKEN).build()

    app.add_handler(CommandHandler("start",  cmd_start))
    app.add_handler(CommandHandler("myplan", cmd_myplan))
    app.add_handler(CommandHandler("myid",   cmd_myid))
    app.add_handler(CommandHandler("help",   cmd_help))
    app.add_handler(CallbackQueryHandler(handle_fallback_save_link,
                                         pattern="^(save_link|cancel)$"))
    app.add_handler(CallbackQueryHandler(handle_callback))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

    print("البوت يعمل...")
    app.run_polling()


if __name__ == "__main__":
    main()
