import json, urllib.request
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
import time

TOKEN='p2lbgWkFrykA4QyUmpHihzmc5BNzIABq'
AUTH='Bearer AuHLIRR82MvrdTTeaQKUxdA7mlNuk0WD6NnX2ffpn0wqeMP5zwkCClOHClRIbCFf'
BASE='https://hrrejgh.com/wecima15/public/api'
OUTPUT=Path('/var/www/html/panel/public/all_movies.json')

WORKERS = 80
TIMEOUT = 8
SAVE_EVERY = 100
BATCH_SIZE = 1000
STOP_AFTER_EMPTY = 10000

HEADERS={
    'Accept':'application/json',
    'Authorization':AUTH,
    'PackageName':'com.radiotn.tunisie',
    'User-Agent':'EasyPlex (Android 15; SM-F956B; samsung q6q; en)'
}

def fetch_movie(mid):
    try:
        req = urllib.request.Request(
            f'{BASE}/media/detail/{mid}/{TOKEN}',
            headers=HEADERS
        )
        with urllib.request.urlopen(req, timeout=TIMEOUT) as r:
            data = json.loads(r.read().decode())
    except:
        return None

    if not data.get("id") or not data.get("title"):
        return None

    return {
        "id": data.get("id"),
        "title": data.get("title"),
        "subtitle": data.get("subtitle"),
        "overview": data.get("overview"),
        "poster_path": data.get("poster_path"),
        "backdrop_path": data.get("backdrop_path"),
        "release_date": data.get("release_date"),
        "runtime": data.get("runtime"),
        "rating": data.get("rating"),
        "genres": [g.get("name") for g in data.get("genres", [])],
        "videos": [
            {
                "server": v.get("server"),
                "link": v.get("link"),
                "header": v.get("header"),
                "useragent": v.get("useragent")
            }
            for v in data.get("videos", [])
            if v.get("status", 1) == 1
        ]
    }

def save(movies):
    movies_sorted = sorted(movies, key=lambda x: int(x.get("id", 0)))
    OUTPUT.parent.mkdir(parents=True, exist_ok=True)
    tmp = OUTPUT.with_suffix(".json.tmp")
    tmp.write_text(json.dumps(movies_sorted, ensure_ascii=False, indent=2), encoding="utf-8")
    tmp.replace(OUTPUT)

def main():
    movies = []
    found_ids = set()
    start = time.time()

    checked = 0
    next_id = 1
    empty_streak = 0

    print(f"START unlimited export | workers={WORKERS} | stop_after_empty={STOP_AFTER_EMPTY}", flush=True)

    while True:
        ids = list(range(next_id, next_id + BATCH_SIZE))
        next_id += BATCH_SIZE

        found_in_batch = 0

        with ThreadPoolExecutor(max_workers=WORKERS) as ex:
            futures = {ex.submit(fetch_movie, mid): mid for mid in ids}

            for fut in as_completed(futures):
                checked += 1
                movie = fut.result()

                if movie and movie["id"] not in found_ids:
                    found_ids.add(movie["id"])
                    movies.append(movie)
                    found_in_batch += 1
                    empty_streak = 0
                else:
                    empty_streak += 1

                if checked % SAVE_EVERY == 0:
                    save(movies)
                    elapsed = int(time.time() - start)
                    print(f"checked={checked} last_id={ids[-1]} saved={len(movies)} empty_streak={empty_streak} elapsed={elapsed}s", flush=True)

        save(movies)

        if found_in_batch == 0:
            print(f"batch_empty ids={ids[0]}..{ids[-1]} empty_streak={empty_streak}", flush=True)

        if empty_streak >= STOP_AFTER_EMPTY:
            print("STOP: reached end, too many empty IDs", flush=True)
            break

    save(movies)
    print("DONE", flush=True)
    print(f"saved={len(movies)}", flush=True)
    print(str(OUTPUT), flush=True)

if __name__ == "__main__":
    main()
