#!/usr/bin/env python3

import requests
import re
import json
import time
from pathlib import Path
from datetime import datetime, timezone, timedelta


# ============================================================
# CONFIG
# ============================================================

# FREE kanály – DVR sa volá BEZ Bearer tokenu
FREE_CIDS = {
    "3884",
}

INPUT_M3U = Path(
    "/opt/epg/megahit.m3u"
)

OUTPUT_M3U = Path(
    "/opt/epg/megahit_catchup.m3u"
)

ACCESS_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGguc3dlZXQudHYiLCJzdWIiOiIxMDI5MTE0NjUzIiwiZXhwIjoxNzkwMTkxMzg4LCJpYXQiOjE3OTAxODA1ODgsImp0aSI6ImY2MGYzZjc1LTc0YzQtNGYyZS1iMDc4LWJmNzhjNjRjYTljZCIsImJpbGxpbmdfaWQiOjEsInByb2ZpbGVfaWQiOiIzVHZ4cFQiLCJkZXZpY2UiOnsidHlwZSI6MjIsImZpcm13YXJlIjp7InZlcnNpb25Db2RlIjoxLCJ2ZXJzaW9uU3RyaW5nIjoiOS4wLjk2In0sInN1Yl90eXBlIjo0MCwibW9kZWwiOiJNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvMTUzLjAuMC4wIFNhZmFyaS81MzcuMzYgRWRnLzE1My4wLjAuMCIsInV1aWQiOiI5NWFhZjAzYi1mMzcyLTQ5YzEtOGY5MC1lYTg2YTIzYjQ2ODciLCJzY3JlZW5faW5mbyI6eyJ3aWR0aCI6MTUzNiwiaGVpZ2h0Ijo4NjQsImFzcGVjdFJhdGlvIjo2fSwiYXBwbGljYXRpb24iOnsidHlwZSI6Mn0sInN1cHBvcnRlZF9kcm0iOnsid2lkZXZpbmVfbW9kdWxhciI6dHJ1ZX0sImRybV9pbmZvIjp7IndpZGV2aW5lX2luZm8iOnsic2VjdXJpdHlfbGV2ZWwiOjN9fX0sImlwIjoiMTkzLjEyMy4xODcuMjQ3IiwiY291bnRyeV9jb2RlIjoiR0IifQ.TUvg5oTivTIqFrQckTMnGBec8VX8CbximWfFrMeyXwU"


OPEN_STREAM_API = (
    "https://api.sweet.tv/TvService/OpenStream.json"
)

EPG_URL_TEMPLATE = (
    "https://staticeu.sweet.tv/tv/epg/v3/{cid}/{date}/cs.json"
)


# ============================================================
# NASTAVENIA
# ============================================================

DAYS_BACK = 7
TIMEOUT = 20
DELAY = 0.15

USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/151.0.0.0 Safari/537.36 Edg/151.0.0.0"
)


# ============================================================
# SESSION
# ============================================================

session = requests.Session()

session.headers.update({
    "User-Agent": USER_AGENT,
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "sk,cz,hu,pl,en;q=0.9",
    "Content-Type": "application/json",
    "Origin": "https://sweet.tv",
    "Referer": "https://sweet.tv/",
})


# ============================================================
# BEARER
# ============================================================
def auth_headers():

    if not ACCESS_TOKEN:
        return {}

    return {
        "Authorization": f"Bearer {ACCESS_TOKEN}"
    }


# ============================================================
# PARSE M3U
# ============================================================

def load_channels(filename):

    channels = []

    try:

        lines = filename.read_text(
            encoding="utf-8",
            errors="ignore"
        ).splitlines()

    except Exception as e:

        print("CHYBA pri čítaní M3U:", e)
        return []

    for line in lines:

        line = line.strip()

        if not line.startswith("#EXTINF:"):
            continue

        cid_match = re.search(
            r'cid="(\d+)"',
            line
        )

        if not cid_match:
            continue

        cid = cid_match.group(1)

        name_match = re.search(
            r'tvg-name="([^"]*)"',
            line
        )

        name = (
            name_match.group(1)
            if name_match
            else ""
        )

        logo_match = re.search(
            r'tvg-logo="([^"]*)"',
            line
        )

        logo = (
            logo_match.group(1)
            if logo_match
            else ""
        )

        channels.append({
            "cid": cid,
            "name": name,
            "logo": logo
        })

    return channels


# ============================================================
# GET EPG
# ============================================================

def get_epg(cid, date_string):

    url = EPG_URL_TEMPLATE.format(
        cid=cid,
        date=date_string
    )

    print()
    print("EPG:")
    print(url)

    try:

        response = session.get(
            url,
            timeout=TIMEOUT
        )

        print(
            "HTTP:",
            response.status_code
        )

        if response.status_code != 200:
            return []

        data = response.json()

        if not isinstance(data, list):
            return []

        print(
            "PROGRAMS:",
            len(data)
        )

        return data

    except Exception as e:

        print(
            "EPG ERROR:",
            e
        )

        return []


# ============================================================
# OPEN DVR STREAM
# ============================================================

def open_dvr(cid, epg_id):

    payload = {
        "channel_id": int(cid),
        "epg_id": int(epg_id)
    }

    # ------------------------------------------------------------
    # FREE kanál = BEZ Bearer tokenu
    # Ostatné kanály = Bearer token
    # ------------------------------------------------------------

    if str(cid) in FREE_CIDS:
        headers = {}
        print("DVR AUTH: NIE (FREE)")
    else:
        headers = auth_headers()
        print("DVR AUTH: ÁNO (Bearer)")

    try:

        response = session.post(
            OPEN_STREAM_API,
            headers=headers,
            json=payload,
            timeout=TIMEOUT
        )

        print(
            f"DVR: CID={cid} EPG_ID={epg_id}"
        )

        print(
            "HTTP:",
            response.status_code
        )

        try:

            data = response.json()

        except Exception:

            print(
                "DVR: INVALID JSON"
            )

            return None

        result = data.get("result")

        print(
            "RESULT:",
            result
        )

        if result != "OK":

            print(
                json.dumps(
                    data,
                    ensure_ascii=False
                )
            )

            return None

        url = data.get("url")

        if not url:

            http_stream = data.get(
                "http_stream"
            )

            if isinstance(
                http_stream,
                dict
            ):

                host = http_stream.get(
                    "host",
                    {}
                )

                address = host.get(
                    "address"
                )

                path = http_stream.get(
                    "url"
                )

                if address and path:

                    url = (
                        "https://"
                        + address
                        + path
                    )

        if not url:
            return None

        print(
            "DVR URL:",
            url
        )

        return url

    except requests.RequestException as e:

        print(
            "DVR REQUEST ERROR:",
            e
        )

        return None

# ============================================================
# FORMAT TIME
# ============================================================

def format_time(timestamp):

    try:

        dt = datetime.fromtimestamp(
            int(timestamp),
            timezone.utc
        )

        return dt.strftime(
            "%H:%M"
        )

    except Exception:

        return "??:??"


# ============================================================
# MAIN
# ============================================================

def main():

    print()
    print("#" * 70)
    print("# SWEET TV CATCH-UP GENERATOR")
    print("#" * 70)

    print()
    print("INPUT :", INPUT_M3U)
    print("OUTPUT:", OUTPUT_M3U)
    print(
        "AUTH  :",
        "Bearer ÁNO"
        if ACCESS_TOKEN
        else "Bearer NIE"
    )
    
    if not ACCESS_TOKEN and not FREE_CIDS:
        print()
        print("CHYBA: Nie je ACCESS_TOKEN ani FREE_CIDS.")
        return

    # ========================================================
    # LOAD CHANNELS
    # ========================================================

    channels = load_channels(
        INPUT_M3U
    )

    if not channels:

        print(
            "Nenašli sa žiadne CID."
        )

        return

    print()
    print(
        "KANÁLOV:",
        len(channels)
    )

    # ========================================================
    # OUTPUT
    # ========================================================

    output = [
        "#EXTM3U"
    ]

    total_programs = 0
    total_dvr = 0
    failed_dvr = 0

    # ========================================================
    # DATES
    # ========================================================

    today = datetime.now(
        timezone.utc
    ).date()

    dates = []

    for i in range(DAYS_BACK):

        d = today - timedelta(
            days=i
        )

        dates.append(
            d.strftime("%d-%m-%Y")
        )

    # ========================================================
    # CHANNELS
    # ========================================================

    for channel in channels:

        cid = channel["cid"]
        channel_name = channel["name"]
        logo = channel["logo"]

        print()
        print("=" * 70)
        print(
            f"CHANNEL: {channel_name}  CID={cid}"
        )
        print("=" * 70)

        for date_string in dates:

            epg = get_epg(
                cid,
                date_string
            )

            if not epg:
                continue

            now = int(
                datetime.now(
                    timezone.utc
                ).timestamp()
            )

            for program in epg:

                epg_id = program.get(
                    "id"
                )

                title = program.get(
                    "text",
                    "Unknown"
                )

                start = program.get(
                    "time_start"
                )

                stop = program.get(
                    "time_stop"
                )

                available = program.get(
                    "available",
                    False
                )

                if not epg_id:
                    continue

                if not start or not stop:
                    continue

                # ------------------------------------------------
                # IBA UKONČENÉ PROGRAMY
                # ------------------------------------------------

                if int(stop) > now:
                    continue

                # ------------------------------------------------
                # MUSÍ BYŤ AVAILABLE
                # ------------------------------------------------

                if not available:
                    continue

                total_programs += 1

                print()
                print(
                    "-" * 60
                )

                print(
                    "PROGRAM:",
                    title
                )

                print(
                    "EPG ID:",
                    epg_id
                )

                print(
                    "TIME:",
                    format_time(start),
                    "-",
                    format_time(stop)
                )

                # ------------------------------------------------
                # DVR
                # ------------------------------------------------

                dvr_url = open_dvr(
                    cid,
                    epg_id
                )

                if not dvr_url:

                    failed_dvr += 1

                    print(
                        "DVR FAILED"
                    )

                    continue

                total_dvr += 1

                # ------------------------------------------------
                # M3U
                # ------------------------------------------------

                safe_title = (
                    title
                    .replace('"', "'")
                    .strip()
                )

                extinf = (
                    '#EXTINF:-1 '
                    f'cid="{cid}" '
                    f'tvg-id="{cid}" '
                    f'tvg-name="{safe_title}" '
                    f'tvg-logo="{logo}" '
                    'group-title="Catch-up" '
                    f'catchup="default" '
                    f'catchup-days="{DAYS_BACK}",'
                    f'{safe_title}'
                )

                output.append(
                    extinf
                )

                output.append(
                    '#EXTVLCOPT:http-user-agent='
                    + USER_AGENT
                )

                output.append(
                    '#KODIPROP:http-user-agent='
                    + USER_AGENT
                )

                output.append(
                    dvr_url
                )

                time.sleep(
                    DELAY
                )

    # ========================================================
    # WRITE
    # ========================================================

    try:

        OUTPUT_M3U.write_text(
            "\n".join(output)
            + "\n",
            encoding="utf-8"
        )

    except Exception as e:

        print()
        print(
            "CHYBA PRI ZÁPISE:"
        )

        print(e)

        return

    # ========================================================
    # SUMMARY
    # ========================================================

    print()
    print("#" * 70)
    print("# HOTOVO")
    print("#" * 70)

    print(
        "Kanály           :",
        len(channels)
    )

    print(
        "EPG programy     :",
        total_programs
    )

    print(
        "DVR OK           :",
        total_dvr
    )

    print(
        "DVR FAILED       :",
        failed_dvr
    )

    print(
        "Výstup           :",
        OUTPUT_M3U
    )

    print("#" * 70)


# ============================================================
# START
# ============================================================

if __name__ == "__main__":
    main()
