import asyncio
import json
import os
import shutil
import time
import traceback
from dotenv import load_dotenv
from pyrogram import Client
from pyrogram.errors import FloodWait

load_dotenv()

# =========================================================
# تنظیمات
# =========================================================

API_ID = int(os.getenv("API_ID"))
API_HASH = os.getenv("API_HASH")

# پوشه مخصوص آپلود و چت مقصد
UPLOAD_DIR = os.getenv("UPLOAD_DIR", "./uploads")
TARGET_CHAT_ID = int(os.getenv("TARGET_CHAT_ID", "-1001155301071"))

VALID_EXTENSIONS = (".mp4", ".mkv", ".mov", ".avi", ".webm")
MAX_RETRIES = 5

app = Client(
    "uploader_account",
    api_id=API_ID,
    api_hash=API_HASH,
    sleep_threshold=0
)


# =========================================================
# استخراج متادیتا و ساخت تامبنیل با ffprobe / ffmpeg
# =========================================================

async def get_video_metadata(video_path: str):
    """استخراج طول، عرض و مدت‌زمان ویدیو با ffprobe"""
    duration, width, height = 0, 0, 0
    cmd = [
        "ffprobe",
        "-v", "quiet",
        "-print_format", "json",
        "-show_streams",
        "-show_format",
        video_path
    ]

    try:
        proc = await asyncio.create_subprocess_exec(
            *cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        stdout, _ = await proc.communicate()
        data = json.loads(stdout.decode('utf-8'))

        if "format" in data and "duration" in data["format"]:
            duration = int(float(data["format"]["duration"]))

        if "streams" in data:
            for stream in data["streams"]:
                if stream.get("codec_type") == "video":
                    width = int(stream.get("width", 0))
                    height = int(stream.get("height", 0))
                    break
    except Exception as e:
        print(f"⚠️ خطای ffprobe: {e}")

    return duration, width, height


async def generate_thumbnail(video_path: str, thumb_path: str):
    """ساخت تصویر بندانگشتی از ثانیه ۱ ویدیو با ffmpeg"""
    try:
        cmd = [
            "ffmpeg", "-y",
            "-i", video_path,
            "-ss", "00:00:01",
            "-vframes", "1",
            thumb_path
        ]
        proc = await asyncio.create_subprocess_exec(
            *cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        await proc.communicate()

        if os.path.exists(thumb_path) and os.path.getsize(thumb_path) > 0:
            return thumb_path
    except Exception as e:
        print(f"⚠️ خطای ساخت تامبنیل: {e}")
    return None


# =========================================================
# پردازش و ارسال ویدیو
# =========================================================

async def upload_single_file(file_path: str) -> bool:
    file_name = os.path.basename(file_path)
    thumb_path = f"{file_path}_thumb.jpg"

    print(f"\n🎬 در حال استخراج متادیتای: {file_name}")
    duration, width, height = await get_video_metadata(file_path)
    thumb = await generate_thumbnail(file_path, thumb_path)

    caption = os.path.splitext(file_name)[0]
    last_update_time = time.time()

    async def progress(current, total):
        nonlocal last_update_time
        if time.time() - last_update_time > 5:
            percent = (current / total) * 100
            uploaded_mb = current / (1024 * 1024)
            total_mb = total / (1024 * 1024)
            print(f"📤 {file_name} | {percent:.1f}% | {uploaded_mb:.1f}/{total_mb:.1f} MB")
            last_update_time = time.time()

    network_retry = 0

    while True:
        try:
            print(f"🚀 شروع ارسال به تلگرام...")
            await app.send_video(
                chat_id=TARGET_CHAT_ID,
                video=file_path,
                caption=f"`{caption}`",
                duration=duration,
                width=width,
                height=height,
                thumb=thumb,
                progress=progress
            )

            print(f"✅ آپلود با موفقیت انجام شد: {file_name}")

            # پاکسازی تامبنیل
            if thumb and os.path.exists(thumb):
                os.remove(thumb)

            return True

        except FloodWait as e:
            print(f"⏳ FloodWait: {e.value} ثانیه صبر کنید...")
            await asyncio.sleep(e.value + 1)
            continue

        except Exception as e:
            network_retry += 1
            print(f"❌ خطا در آپلود {file_name}: {e}")
            traceback.print_exc()

            if network_retry >= MAX_RETRIES:
                print(f"🚫 انصراف از ارسال فایل پس از {MAX_RETRIES} تلاش ناموفق.")
                if thumb and os.path.exists(thumb):
                    os.remove(thumb)
                return False

            await asyncio.sleep(10 * network_retry)


# =========================================================
# لایت‌لوپ اسکن پوشه uploads
# =========================================================

async def start_uploader_loop():
    os.makedirs(UPLOAD_DIR, exist_ok=True)
    print(f"👀 مانیتورینگ پوشه آپلود فعال شد: {UPLOAD_DIR}")

    while True:
        try:
            files = [
                f for f in os.listdir(UPLOAD_DIR)
                if f.lower().endswith(VALID_EXTENSIONS)
            ]

            for file_name in files:
                file_path = os.path.join(UPLOAD_DIR, file_name)

                # اطمینان از کامل بودن فایل (عدم تغییر حجم طی ۱ ثانیه)
                initial_size = os.path.getsize(file_path)
                await asyncio.sleep(1)
                if os.path.getsize(file_path) != initial_size:
                    continue

                success = await upload_single_file(file_path)

                if success:
                    # حذف فایل اصلی پس از ارسال کامل
                    if os.path.exists(file_path):
                        os.remove(file_path)
                        print(f"🗑️ فایل از پوشه آپلود حذف شد: {file_name}")

                await asyncio.sleep(3)

        except Exception as e:
            print(f"⚠️ خطای حلقه اسکن: {e}")

        await asyncio.sleep(5)


if __name__ == "__main__":
    print("🚀 در حال استارت سرویس آپلودر...")
    app.start()
    
    try:
        app.run(start_uploader_loop())
    except KeyboardInterrupt:
        pass
    finally:
        app.stop()