"""YouTube downloader — videos, shorts, audio via yt-dlp with quality selection.
v3.0: enabled with format picking, audio-only mode."""
from __future__ import annotations

import logging
import re
import time

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.constants import ParseMode
from telegram.ext import CallbackQueryHandler, ContextTypes, MessageHandler, filters

from bot.handlers.dl_utils import (
    TEMP_DIR,
    dl_via_ytdlp,
    extract_info_ytdlp,
    format_size,
    estimate_size,
)

logger = logging.getLogger(__name__)

YOUTUBE_RE = re.compile(
    r"(?:https?://)?(?:www\.)?(?:youtube\.com/watch\?v=|youtu\.be/|youtube\.com/shorts/|m\.youtube\.com/watch\?v=)([a-zA-Z0-9_\-]{11})",
    re.IGNORECASE,
)

QUALITY_OPTIONS = [
    ("🎥 بهترین کیفیت", "bestvideo+bestaudio/best"),
    ("🖥 1080p", "bestvideo[height<=1080]+bestaudio/best[height<=1080]"),
    ("💻 720p", "bestvideo[height<=720]+bestaudio/best[height<=720]"),
    ("📱 480p", "bestvideo[height<=480]+bestaudio/best[height<=480]"),
    ("🎵 فقط صدا (MP3)", "bestaudio/best"),
]

_pending: dict[tuple[int, int], dict] = {}
PENDING_TTL = 300


async def youtube_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    message = update.message
    if not message or not message.text:
        return

    urls = YOUTUBE_RE.findall(message.text)
    if not urls:
        return

    status = await message.reply_text("🔍 دریافت اطلاعات ویدیو...")

    for video_id in urls:
        url = f"https://youtube.com/watch?v={video_id}"
        try:
            info = await extract_info_ytdlp(url)
        except Exception:
            await status.edit_text(f"❌ ویدیو دریافت نشد (ممکنه حذف یا خصوصی شده باشه).")
            continue

        if not info:
            # Fallback: offer direct download without info
            await _send_quality_buttons(message, video_id, "unknown", status)
            continue

        title = info.get("title", "بدون عنوان")[:80]
        duration = info.get("duration", 0)
        author = info.get("uploader", info.get("channel", "unknown"))
        estimated = estimate_size(info)

        dur_str = f"{duration//60}:{duration%60:02d}" if duration else "?"

        await status.edit_text(
            f"📹 **{title}**\n👤 {author}\n⏱ {dur_str}\n💾 ~{estimated}\n\n"
            f"کیفیت را انتخاب کنید:",
            parse_mode=ParseMode.MARKDOWN,
        )

        await _send_quality_buttons(message, video_id, title, status)


async def _send_quality_buttons(message, video_id: str, title: str, status_msg) -> None:
    buttons = [
        [InlineKeyboardButton(label, callback_data=f"ytdl:{fmt}:{video_id}")]
        for label, fmt in QUALITY_OPTIONS
    ]
    sent = await message.reply_text(
        f"⬇️ {title[:50]}",
        reply_markup=InlineKeyboardMarkup(buttons),
    )
    key = (message.chat_id, sent.message_id)
    _pending[key] = {
        "video_id": video_id,
        "timeout": time.monotonic() + PENDING_TTL,
    }
    try:
        await status_msg.delete()
    except Exception:
        pass


async def yt_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    query = update.callback_query
    if not query or not query.data:
        return
    await query.answer()

    parts = query.data.split(":", 2)
    if len(parts) < 3:
        return
    action, fmt, video_id = parts[0], parts[1], parts[2]
    if action != "ytdl":
        return

    key = (query.message.chat_id, query.message.message_id)
    pending = _pending.pop(key, None)
    if not pending:
        await query.edit_message_text("⏰ زمان انتخاب گذشته. دوباره لینک را بفرستید.")
        return

    is_audio = "bestaudio" in fmt
    ext = "mp3" if is_audio else "mp4"
    out_fn = f"yt_{video_id}.{ext}"

    await query.edit_message_text("📥 در حال دانلود...")

    if is_audio:
        output = await dl_via_ytdlp(
            f"https://youtube.com/watch?v={video_id}",
            out_fn, fmt,
            postprocessor_args=["-f", "mp3", "--audio-format", "mp3"],
        )
    else:
        output = await dl_via_ytdlp(
            f"https://youtube.com/watch?v={video_id}",
            out_fn, fmt,
        )

    if not output:
        await query.edit_message_text("❌ دانلود ناموفق. لینک را دوباره بفرستید.")
        return

    try:
        filesize = output.stat().st_size
        await query.edit_message_text(f"📤 آپلود... ({format_size(filesize)})")

        with open(output, "rb") as f:
            if is_audio:
                await query.message.reply_audio(f, title=f"YouTube Audio", write_timeout=300)
            elif filesize > 50 * 1024 * 1024:
                await query.message.reply_document(
                    f, filename=f"youtube_{video_id}.mp4", write_timeout=300,
                )
            else:
                await query.message.reply_video(f, write_timeout=300, supports_streaming=True)
    finally:
        output.unlink(missing_ok=True)

    try:
        await query.message.delete()
    except Exception:
        pass


def register(app) -> None:
    app.add_handler(
        MessageHandler(filters.TEXT & ~filters.COMMAND, youtube_handler),
        group=-2,
    )
    app.add_handler(
        CallbackQueryHandler(yt_callback, pattern=r"^ytdl:"),
        group=-2,
    )
    logger.info("YouTube downloader registered (v3.0)")
