#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import os
import json
import re
import subprocess
import urllib.parse
from typing import List, Dict, Optional, Tuple

# =====================================================
# KONFIG
# =====================================================

# Putanja do MAX TV M3U liste
MAX_M3U_PATH = "/home/max.m3u"

# Prefiks koji želiš da se vidi u panelu
PANEL_PREFIX = "MaxTV HR | "

# PROXY koji si dao za MAX
PROXY_URL = "proxy upisati"

# User-Agent za curl tokenizaciju
CURL_USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/130.0.0.0 Safari/537.36"
)

# =====================================================
# POMOĆNE FUNKCIJE
# =====================================================

def parse_params(args: List[str], key: str) -> Optional[str]:
    """Prosti parser CLI parametara key=value."""
    for arg in args:
        if arg.startswith(key + "="):
            return arg.split("=", 1)[1]
    return None


def norm_name(s: str) -> str:
    """Normalizacija imena kanala za usporedbu."""
    if not s:
        return ""
    s = s.strip().lower()
    s = re.sub(r"[\s\-]+", "", s)
    return s


def load_max_m3u(path: str = MAX_M3U_PATH) -> List[Dict[str, str]]:
    """
    Učitaj /home/max.m3u i vrati listu:
    [{ "name": "SK1", "url": "https://...index.mpd?decryption_key=KID:KEY" }, ...]
    """
    channels: List[Dict[str, str]] = []

    if not os.path.exists(path):
        sys.stderr.write(f"DEBUG: M3U file not found: {path}\n")
        return channels

    current_name: Optional[str] = None

    with open(path, "r", encoding="utf-8", errors="ignore") as f:
        for line in f:
            line = line.strip()
            if not line:
                continue

            if line.startswith("#EXTINF"):
                # primjer: #EXTINF:-1,SK1
                if "," in line:
                    current_name = line.split(",", 1)[1].strip()
                else:
                    current_name = line
            elif line.startswith("#"):
                continue
            else:
                # URL linija
                if current_name:
                    channels.append({"name": current_name, "url": line})
                    current_name = None

    sys.stderr.write(f"DEBUG: Loaded {len(channels)} entries from {path}\n")
    return channels


def split_url_and_key(full_url: str) -> Tuple[str, Optional[str]]:
    """
    Iz URL-a odvoji decryption_key, npr:
      https://.../index.mpd?foo=1&decryption_key=KID:KEY&bar=2
    → ("https://.../index.mpd?foo=1&bar=2", "KID:KEY")
    """
    lower = full_url.lower()
    if "decryption_key=" not in lower:
        return full_url, None

    if "?" in full_url:
        base_part, query = full_url.split("?", 1)
    else:
        base_part, query = full_url, ""

    parts = [p for p in query.split("&") if p]
    new_parts = []
    key_value = None

    for p in parts:
        if p.lower().startswith("decryption_key="):
            key_value = p.split("=", 1)[1]
        else:
            new_parts.append(p)

    if new_parts:
        base_without_key = base_part + "?" + "&".join(new_parts)
    else:
        base_without_key = base_part

    return base_without_key, key_value


def get_tokenized_url_with_curl(manifest_url: str) -> str:
    """
    Ista logika kao u Yettel skripti: curl -L -w %{url_effective}
    Radi preko PROXY_URL. Ako nešto pukne, vraća originalni manifest_url.
    """
    try:
        cmd = [
            "curl",
            "-L",
            "-s",
            "-o", "/dev/null",
            "-w", "%{url_effective}",
            "-H", f"User-Agent: {CURL_USER_AGENT}",
        ]
        if PROXY_URL:
            cmd += ["-x", PROXY_URL]

        cmd.append(manifest_url)

        out = subprocess.check_output(cmd, timeout=30)
        token_url = out.decode().strip()

        if not token_url.startswith("http"):
            sys.stderr.write("DEBUG: curl nije vratio ispravan URL, vraćam original\n")
            return manifest_url

        sys.stderr.write(f"DEBUG: Tokenized URL: {token_url}\n")
        return token_url

    except Exception as e:
        sys.stderr.write(f"DEBUG: get_tokenized_url_with_curl error: {e}\n")
        return manifest_url


def build_final_url(token_url: str, key_value: Optional[str]) -> str:
    """
    Na tokenizirani URL ponovo dodaje decryption_key=KID:KEY, ako postoji.
    """
    if not key_value:
        return token_url

    sep = "&" if "?" in token_url else "?"
    final_url = f"{token_url}{sep}decryption_key={key_value}"
    sys.stderr.write(f"DEBUG: Final URL with key: {final_url}\n")
    return final_url


# =====================================================
# AKCIJE
# =====================================================

def action_channels() -> None:
    """
    action=channels
    → generiše listu kanala za O11 provider,
      kao Yettel skripta, ali na osnovu /home/max.m3u

    VAŽNO:
    - Name: 'MaxTV HR | <ime iz m3u>'
    - ManifestScript: 'id=' + URL-encoded ime iz m3u
      (npr. 'id=ARENA%20SPORT%201') da ne bude problema sa razmacima i '|'
    """
    channels = load_max_m3u()
    if not channels:
        print("{}")
        return

    out = {"Channels": []}

    for ch in channels:
        m3u_name = ch["name"].strip()
        panel_name = f"{PANEL_PREFIX}{m3u_name}"

        safe_id = urllib.parse.quote(m3u_name)

        channel_info = {
            "Name": panel_name,
            "Mode": "live",
            "SessionManifest": True,
            # O11 će dodati action=manifest, ovdje ide samo ostatak parametara
            "ManifestScript": "id=" + safe_id,
            "CdmType": "none",
            "UseCdm": False,
            "Cdm": "",
            "Video": "best",
            "OnDemand": True,
            "SpeedUp": True,
        }
        out["Channels"].append(channel_info)

    print(json.dumps(out))


def action_manifest(encoded_id: str) -> None:
    """
    action=manifest&id=<URL-encoded m3u ime>

    1) decode id -> m3u_name (npr. 'Arena Fight')
    2) u /home/max.m3u nađe taj kanal
    3) uzme URL, odvoji decryption_key
    4) curl + proxy -> tokenizirani URL
    5) vrati JSON (kao Yettel skripta), sa ponovno dodanim decryption_key=KID:KEY
    """
    m3u_name = urllib.parse.unquote(encoded_id or "")
    if not m3u_name:
        sys.stderr.write("DEBUG: action=manifest bez id parametra\n")
        print("{}")
        return

    channels = load_max_m3u()
    if not channels:
        print("{}")
        return

    wanted = norm_name(m3u_name)
    sys.stderr.write(
        f"DEBUG: encoded_id='{encoded_id}' -> m3u_name='{m3u_name}' -> wanted='{wanted}'\n"
    )

    target = None

    # prvo exact match
    for ch in channels:
        if norm_name(ch["name"]) == wanted:
            target = ch
            break

    # fallback: contains
    if target is None:
        for ch in channels:
            if wanted and wanted in norm_name(ch["name"]):
                target = ch
                break

    if target is None:
        sys.stderr.write(
            f"DEBUG: Channel '{m3u_name}' not found in {MAX_M3U_PATH}\n"
        )
        print("{}")
        return

    original_url = target["url"]
    sys.stderr.write(f"DEBUG: Found M3U name='{target['name']}' url='{original_url}'\n")

    url_without_key, key_value = split_url_and_key(original_url)
    sys.stderr.write(f"DEBUG: URL without key: {url_without_key}\n")
    if key_value:
        sys.stderr.write(f"DEBUG: Extracted key: {key_value}\n")

    token_url = get_tokenized_url_with_curl(url_without_key)
    final_url = build_final_url(token_url, key_value)

    out = {
        "Cdn": [],
        "ManifestUrl": final_url,
        "Headers": {
            "Manifest": {"User-Agent": "Mozilla/5.0"},
            "Media": {"User-Agent": "Mozilla/5.0"},
        },
        "Heartbeat": {"Url": "", "Params": "", "PeriodMs": 300000},
    }
    print(json.dumps(out))


def main() -> None:
    action = parse_params(sys.argv, "action")
    raw_id = parse_params(sys.argv, "id")  # kodiran (ARENA%20SPORT%201)

    if action == "channels":
        action_channels()
    elif action == "manifest" and raw_id:
        action_manifest(raw_id)
    else:
        # za svaki drugi slučaj vrati prazan JSON
        print("{}")


if __name__ == "__main__":
    main()