import base64
import json
import time
import urllib.parse
import urllib.request
from pathlib import Path

BASE = "http://89.117.53.204:9988"
LOCAL_BASE = "http://127.0.0.1:9988"

INPUT = Path("/var/www/html/IMBD/streamimdb-top.json")
OUTPUT = Path("/var/www/html/IMBD/streamimdb-top.m3u")

ADMIN_USER = "alraqi"
ADMIN_PASS = "21122233"

AUTH = "Basic " + base64.b64encode(
    f"{ADMIN_USER}:{ADMIN_PASS}".encode()
).decode()

MAX_ROUNDS = 3
WAIT_BETWEEN_ROUNDS = 10

items = json.loads(INPUT.read_text(encoding="utf-8"))


def esc(value):
    return (
        str(value or "")
        .replace('"', "&quot;")
        .replace("\n", " ")
        .replace("\r", " ")
    )


def request_headers():
    return {
        "Accept": "application/json, application/vnd.apple.mpegurl, */*",
        "Authorization": AUTH,
        "User-Agent": "Mozilla/5.0",
    }


def proxy_is_working(play_url):
    local_url = play_url.replace(BASE, LOCAL_BASE, 1)

    request = urllib.request.Request(
        local_url,
        headers=request_headers(),
    )

    with urllib.request.urlopen(request, timeout=30) as response:
        body = response.read(4096).decode("utf-8", "ignore")

    return "#EXTM3U" in body


def extract(item):
    code = item.get("code") or "unknown"
    name = item.get("name") or code
    logo = item.get("logo") or item.get("image") or ""

    page = (
        item.get("link")
        or f"https://streamimdb.ru/embed/movie/{code}"
    )

    api = (
        f"{LOCAL_BASE}/api/extractor/pro-extract?url="
        + urllib.parse.quote(page, safe="")
    )

    try:
        request = urllib.request.Request(
            api,
            headers=request_headers(),
        )

        with urllib.request.urlopen(request, timeout=120) as response:
            data = json.loads(
                response.read().decode("utf-8", "ignore")
            )

        direct = ((data or {}).get("best") or {}).get("url") or ""

        if not direct:
            raise RuntimeError("best.url فارغ")

        play = (
            f"{BASE}/api/extractor/proxy?url="
            + urllib.parse.quote(direct, safe="")
        )

        if not proxy_is_working(play):
            raise RuntimeError("رابط البروكسي لا يرجع M3U8")

        entry = (
            f'#EXTINF:-1 tvg-id="{esc(code)}" '
            f'tvg-name="{esc(name)}" '
            f'tvg-logo="{esc(logo)}" '
            f'group-title="StreamIMDB",{esc(name)}\n'
            f"{play}\n"
        )

        return entry, None

    except Exception as error:
        return None, str(error)


results = {}
pending = set(range(len(items)))

for round_number in range(1, MAX_ROUNDS + 1):
    if not pending:
        break

    print(
        f"ROUND: {round_number}/{MAX_ROUNDS} "
        f"PENDING: {len(pending)}",
        flush=True,
    )

    for index in sorted(list(pending)):
        item = items[index]
        code = item.get("code") or "unknown"

        entry, error = extract(item)

        if entry:
            results[index] = entry
            pending.remove(index)

            print(
                f"OK: {code} "
                f"TOTAL: {len(results)}/{len(items)}",
                flush=True,
            )
        else:
            print(
                f"MISS: {code} "
                f"ROUND: {round_number} "
                f"ERROR: {error}",
                flush=True,
            )

    if pending and round_number < MAX_ROUNDS:
        print(
            f"WAIT: {WAIT_BETWEEN_ROUNDS} seconds",
            flush=True,
        )
        time.sleep(WAIT_BETWEEN_ROUNDS)


if not results:
    print(
        "ABORT: لم ينجح أي فيلم، سيتم الاحتفاظ بالقائمة القديمة",
        flush=True,
    )
    raise SystemExit(2)


content = "#EXTM3U\n" + "".join(
    results[index]
    for index in sorted(results)
)

temporary = OUTPUT.with_name(OUTPUT.name + ".tmp")
temporary.write_text(content, encoding="utf-8")
temporary.replace(OUTPUT)

print("DONE", flush=True)
print("Movies:", len(results), flush=True)

if pending:
    missing_codes = [
        items[index].get("code") or "unknown"
        for index in sorted(pending)
    ]
    print(
        "MISSING:",
        ", ".join(missing_codes),
        flush=True,
    )

print("Saved:", OUTPUT, flush=True)
