import os
import sys
import json
import time
import subprocess
import glob
import io
from datetime import datetime

# Fix encoding per Windows
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')

# Force unbuffered output
os.environ['PYTHONUNBUFFERED'] = '1'

def log(msg=""):
    """Print con flush immediato cosi' vedi tutto in tempo reale."""
    print(msg, flush=True)

# ──────────────────────────────────────────────
#  SIUM Extractor — Manifest + Keys Refresher
# ──────────────────────────────────────────────

# Percorsi
BASE_DIR       = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
PROVIDERS_DIR  = os.path.join(BASE_DIR, "providers")
NOWTV_SCRIPT   = os.path.join(BASE_DIR, "scripts", "nowtv.py")
OUTPUT_FILE    = os.path.join(os.path.dirname(__file__), "manifests.json")

# Credenziali
USER     = "luisa.mannina@uniroma1.it"
PASSWORD = "Alice1966!"

# Intervallo di refresh in secondi (1 ora)
REFRESH_INTERVAL = 3600


def load_channels_from_configs():
    channels = []
    seen_ids = set()

    for cfg_path in sorted(glob.glob(os.path.join(PROVIDERS_DIR, "nowtv*.cfg"))):
        try:
            with open(cfg_path, "r", encoding="utf-8") as f:
                data = json.load(f)
        except Exception as e:
            log(f"  [WARN] Impossibile leggere {cfg_path}: {e}")
            continue

        provider_name = data.get("Name", "")
        script_line   = data.get("Script", "")

        category = ""
        for part in script_line.split():
            if part.startswith("category="):
                category = part.split("=", 1)[1]

        for stream in data.get("Streams", []):
            stream_id   = stream.get("Id", "")
            stream_name = stream.get("Name", "")
            params      = stream.get("ScriptParams", "")
            keys_list   = stream.get("Keys", [])

            if stream_id in seen_ids:
                continue
            seen_ids.add(stream_id)

            service_key = ""
            for p in params.split():
                if "serviceKey=" in p:
                    service_key = p.split("=", 1)[1]

            if not service_key:
                continue

            channels.append({
                "id":          stream_id,
                "name":        stream_name,
                "provider":    provider_name,
                "category":    category,
                "serviceKey":  service_key,
                "keys":        keys_list,
            })

    return channels


def extract_manifest(channel):
    cmd = [
        sys.executable, NOWTV_SCRIPT,
        "country=IT",
        f"category={channel['category']}",
        f"serviceKey={channel['serviceKey']}",
        "action=manifest",
        f"user={USER}",
        f"password={PASSWORD}"
    ]

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=20)
        if result.returncode != 0:
            err_msg = result.stderr.strip() or result.stdout.strip()
            log(f"         -> ERRORE: exit code {result.returncode} | {err_msg[:120]}")
            return None
        output = json.loads(result.stdout)
        if "ManifestUrl" in output:
            return output["ManifestUrl"]
        else:
            log(f"         -> ERRORE: {result.stdout.strip()[:120]}")
            return None
    except subprocess.TimeoutExpired:
        log(f"         -> ERRORE: timeout (20s) - lo script si e' bloccato")
        return None
    except json.JSONDecodeError:
        log(f"         -> ERRORE: risposta non JSON: {result.stdout.strip()[:120]}")
        return None
    except Exception as e:
        log(f"         -> ERRORE: {e}")
        return None


def update_all_manifests():
    timestamp = datetime.now().isoformat()
    log()
    log("=" * 60)
    log(f"  SIUM Extractor - Aggiornamento")
    log(f"  {timestamp}")
    log("=" * 60)
    log()

    log("[1/3] Lettura configurazioni .cfg...")
    channels = load_channels_from_configs()
    log(f"       Trovati {len(channels)} canali totali")
    log()

    # Carica dati precedenti
    data = {}
    if os.path.exists(OUTPUT_FILE):
        try:
            with open(OUTPUT_FILE, "r", encoding="utf-8") as f:
                data = json.load(f)
        except Exception:
            pass

    log("[2/3] Estrazione manifest freschi...")
    log()

    success = 0
    failed  = 0
    total   = len(channels)

    for i, ch in enumerate(channels, 1):
        log(f"  [{i}/{total}] {ch['name']}")
        log(f"         Provider: {ch['provider']} | serviceKey={ch['serviceKey']} | category={ch['category']}")

        manifest = extract_manifest(ch)

        entry = {
            "name":        ch["name"],
            "provider":    ch["provider"],
            "category":    ch["category"],
            "serviceKey":  ch["serviceKey"],
            "keys":        ch["keys"],
            "updated_at":  timestamp,
        }

        if manifest:
            entry["manifest_url"] = manifest
            entry["status"] = "ok"
            success += 1
            log(f"         -> OK! Manifest ottenuto")
        else:
            old = data.get(ch["id"], {})
            entry["manifest_url"] = old.get("manifest_url", "")
            entry["status"] = "error"
            entry["last_success"] = old.get("updated_at", "")
            failed += 1

        data[ch["id"]] = entry
        log()

    # Salva
    log("[3/3] Salvataggio manifests.json...")
    with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

    log()
    log("-" * 60)
    log(f"  RISULTATI: {success} OK / {failed} errori / {total} totali")
    log(f"  File: {OUTPUT_FILE}")
    log("-" * 60)
    log()


if __name__ == "__main__":
    log("========================================")
    log("  SIUM Extractor v2.1 - Avviato")
    log(f"  Refresh ogni {REFRESH_INTERVAL // 60} minuti")
    log(f"  Account: {USER}")
    log("========================================")

    while True:
        update_all_manifests()
        log(f"Prossimo aggiornamento tra {REFRESH_INTERVAL // 60} minuti...")
        log()
        time.sleep(REFRESH_INTERVAL)
