###############################################################
PORT = 4323
ADDON_SIG_TTL = 600  # 10 Minuten
###############################################################

import json
import gzip
import requests
import os
from io import BytesIO
import uuid
from flask import Flask, request, Response, abort
import time
import socket
import threading

# ---------------- LÄNDER ----------------

REGIONS = [
    {"language": "nl", "region": "BE"},
]

GEOIP_URL = "https://www.vavoo.tv/geoip"
PING_URL = "https://www.vavoo.tv/api/app/ping"
CATALOG_URL = "https://vavoo.to/mediahubmx-catalog.json"
RESOLVE_URL = "https://vavoo.to/mediahubmx-resolve.json"

LANGUAGE = "de"
REGION = "DE"

HEADERS = {
    "accept": "*/*",
    "user-agent": "electron-fetch/1.0 electron (+https://github.com/arantes555/electron-fetch)",
    "Accept-Language": LANGUAGE,
    "Accept-Encoding": "gzip, deflate",
    "Connection": "close",
}

def decode_response(resp):
    if resp.content[:2] == b'\x1f\x8b':
        return json.loads(gzip.decompress(resp.content))
    return resp.json()

session = requests.Session()
session.headers.update(HEADERS)

# ---------------- GEO + INITIAL PING ----------------

r_geo = session.get(GEOIP_URL)
r_geo.raise_for_status()
geo_data = decode_response(r_geo)

unique_id = str(uuid.uuid4())
current_timestamp = int(time.time() * 1000)

initial_payload = {
    "reason": "app-focus",
    "locale": "de",
    "theme": "dark",
    "metadata": {
        "device": {"type": "desktop", "uniqueId": unique_id},
        "os": {"name": "win32", "version": "Windows 10 Pro", "abis": ["x64"], "host": "Lenovo"},
        "app": {"platform": "electron"},
        "version": {"package": "tv.vavoo.app", "binary": "3.1.8", "js": "3.1.8"},
    },
    "appFocusTime": 0,
    "playerActive": False,
    "playDuration": 0,
    "devMode": False,
    "hasAddon": True,
    "castConnected": False,
    "package": "tv.vavoo.app",
    "version": "3.1.8",
    "process": "app",
    "firstAppStart": current_timestamp,
    "lastAppStart": current_timestamp,
    "ipLocation": None,
    "adblockEnabled": True,
    "proxy": {"supported": ["ss"], "engine": "Mu", "enabled": False, "autoServer": True},
    "iap": {"supported": False},
}

r1 = session.post(PING_URL, json=initial_payload)
r1.raise_for_status()
data1 = decode_response(r1)

# ---------------- ADDON SIG MANAGEMENT ----------------

addon_sig_lock = threading.Lock()
addon_sig_data = {
    "sig": data1.get("addonSig"),
    "ts": time.time()
}

def refresh_addon_sig_if_needed(force=False):
    with addon_sig_lock:
        now = time.time()
        if not force and now - addon_sig_data["ts"] < ADDON_SIG_TTL:
            return addon_sig_data["sig"]

        payload = initial_payload.copy()
        payload["lastAppStart"] = int(time.time() * 1000)

        r = session.post(PING_URL, json=payload)
        r.raise_for_status()
        data = decode_response(r)

        sig = data.get("addonSig")
        if not sig:
            raise RuntimeError("No addonSig received")

        addon_sig_data["sig"] = sig
        addon_sig_data["ts"] = now

        print("[✓] addonSig refreshed")
        return sig

# ---------------- CATALOG LOAD (MULTI-REGION) ----------------

items_by_region = {}

for entry in REGIONS:
    LANGUAGE = entry["language"]
    REGION = entry["region"]
    region_key = f"{LANGUAGE}-{REGION}"

    print(f"[+] Lade Katalog für {region_key}")

    catalog_headers = {
        "content-type": "application/json; charset=utf-8",
        "mediahubmx-signature": addon_sig_data["sig"],
        "user-agent": "MediaHubMX/2",
        "accept": "*/*",
        "Accept-Language": LANGUAGE,
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
    }

    cursor = None

    while True:
        catalog_payload = {
            "language": LANGUAGE,
            "region": REGION,
            "catalogId": "iptv",
            "id": "iptv",
            "adult": False,
            "search": "",
            "sort": "",
            "filter": {},
            "cursor": cursor,
            "clientVersion": "3.0.2"
        }

        r_catalog = session.post(CATALOG_URL, json=catalog_payload, headers=catalog_headers)
        r_catalog.raise_for_status()
        catalog_data = decode_response(r_catalog)

        for item in catalog_data.get("items", []):
            if item.get("type") == "iptv":
                items_by_region.setdefault(region_key, []).append({
                    "id": item["ids"]["id"],
                    "url": item["url"],
                    "name": item["name"],
                    "group": item["group"],
                    "logo": item["logo"],
                    "language": LANGUAGE,
                    "region": REGION
                })

        cursor = catalog_data.get("nextCursor")
        if not cursor:
            break

print(f"[✓] Gesamtanzahl IPTV-Sender: {sum(len(v) for v in items_by_region.values())}")

# ---------------- M3U SAVE (MULTI-FILE) ----------------

LOCAL_IP = "127.0.0.1"

def get_local_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))  # Connecting to Google's DNS server
    local_ip = s.getsockname()[0]  # Getting the local IP address
    s.close()
    print("Local IP address:", local_ip)
    return local_ip
#    return LOCAL_IP

# Unterordner erstellen
PLAYLIST_DIR = "playlists"
os.makedirs(PLAYLIST_DIR, exist_ok=True)

def save_m3u_files():
    local_ip = get_local_ip()

    for region_key, items in items_by_region.items():
        filename = os.path.join(PLAYLIST_DIR, f"vavoo_{region_key}.m3u")
        m3u = "#EXTM3U\n"

        for item in items:
            m3u += (
                f'#EXTINF:-1 tvg-id="{item["id"]}" '
                f'tvg-name="{item["name"]}" '
                f'tvg-logo="{item["logo"]}" '
#                f'group-title="{item["group"]} ({item["region"]})",{item["name"]}\n'
                f'group-title="{item["group"]}",{item["name"]}\n'
            )
            m3u += f"http://{local_ip}:{PORT}/vavoo?channel={item['id']}\n"

        with open(filename, "w", encoding="utf-8") as f:
            f.write(m3u)

        print(f"[✓] {filename} geschrieben")

def save_master_m3u():
    master = "#EXTM3U\n"

    for region_key in items_by_region.keys():
        filename = f"playlists/vavoo_{region_key}.m3u"
        master += f'#EXTINF:-1 group-title="Master",{region_key}\n'
        master += f"{filename}\n"

    with open("vavoo_master.m3u", "w", encoding="utf-8") as f:
        f.write(master)

    print("[✓] vavoo_master.m3u geschrieben")

save_m3u_files()
save_master_m3u()

# ---------------- FLASK APP ----------------

app = Flask(__name__)

@app.route("/vavoo")
def stream_proxy():
    channel_id = request.args.get("channel")
    if not channel_id:
        abort(400)

    channel = None
    for region_items in items_by_region.values():
        for i in region_items:
            if i["id"] == channel_id:
                channel = i
                break

    if not channel:
        abort(404)

    try:
        sig = refresh_addon_sig_if_needed()
    except Exception as e:
        abort(502, str(e))

    resolve_headers = {
        "content-type": "application/json; charset=utf-8",
        "mediahubmx-signature": sig,
        "user-agent": "MediaHubMX/2",
        "accept": "*/*",
        "Accept-Language": channel["language"],
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
    }

    resolve_payload = {
        "language": channel["language"],
        "region": channel["region"],
        "url": channel["url"],
        "clientVersion": "3.0.2"
    }

    r_resolve = session.post(RESOLVE_URL, json=resolve_payload, headers=resolve_headers)

    if r_resolve.status_code == 403:
        sig = refresh_addon_sig_if_needed(force=True)
        resolve_headers["mediahubmx-signature"] = sig
        r_resolve = session.post(RESOLVE_URL, json=resolve_payload, headers=resolve_headers)

    r_resolve.raise_for_status()
    result = decode_response(r_resolve)

    if result:
        return Response(status=302, headers={"Location": result[0]["url"]})

    abort(404)


# ---------------- ALL-IN-ONE PLAYLIST ----------------

@app.route("/playlist.m3u")
def playlist():
    local_ip = get_local_ip()
    m3u = "#EXTM3U\n"

    for region_items in items_by_region.values():
        for item in region_items:
            m3u += (
                f'#EXTINF:-1 tvg-id="{item["id"]}" '
                f'tvg-name="{item["name"]}" '
                f'tvg-logo="{item["logo"]}" '
#                f'group-title="{item["group"]} ({item["region"]})",{item["name"]}\n'
                f'group-title="{item["group"]}",{item["name"]}\n'
            )
            m3u += f"http://{local_ip}:{PORT}/vavoo?channel={item['id']}\n"

    return Response(m3u, mimetype="application/x-mpegURL")


# ---------------- MASTER PLAYLIST ----------------

@app.route("/master.m3u")
def master_playlist():
    try:
        with open("vavoo_master.m3u", "r", encoding="utf-8") as f:
            content = f.read()
        return Response(content, mimetype="application/x-mpegURL")
    except FileNotFoundError:
        return Response("#EXTM3U\n# Master playlist not found\n", mimetype="application/x-mpegURL")


# ---------------- START SERVER ----------------

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)
