# -*- coding: utf-8 -*-
import requests
import re

FUENTES = [
    "http://ktivguth.msostvip.com/get.php?username=9LVMAQVJ&password=W62VGURD&type=m3u_plus&output=m3u8"
]

ARCHIVO_SALIDA = "/mnt/nvme/iptv/solo_canales_en_vivo.m3u"

PATRON_FUTBOL = re.compile(
    r'\b(FOOTBALL|FUTBOL|SOCCER|LALIGA|LA\s+LIGA|PREMIER|CHAMPIONS|UEFA|FIFA|'
    r'DAZN|BEIN|ESPN|EUROSPORT|SKY\s+SPORT|BT\s+SPORT|TNT\s+SPORT|ELEVEN\s+SPORT|'
    r'MOVISTAR\s+LIGA|MOVISTAR\s+SPORT|GOL\s+TV|GOL\s+PLAY|SETANTA|GO3\s+SPORT|'
    r'ARENA\s+SPORT|SPORT\s+KLUB|SWISS\s+SPORT|RTS\s+SPORT|SRF\s+SPORT)\b',
    re.IGNORECASE
)

PATRON_F1 = re.compile(
    r'\b(FORMULA\s*1|FORMULA\s+ONE|F1|MOTORSPORT|MOTORSPORTS|F1\s+TV|F1TV|'
    r'SKY\s+SPORTS\s+F1|SKY\s+F1|F1\s+LIVE)\b',
    re.IGNORECASE
)

PATRON_ADULT = re.compile(
    r'\b(ADULT|XXX|PENTHOUSE|PLAYBOY|EROTIC|EROTICA|BLUE\s+HUSTLER|HUSTLER|'
    r'DORCEL|BABELAND|VIVID|WICKED|PRIVATE|SEX|SEXTV|PORNO|PORN|HARDCORE)\b',
    re.IGNORECASE
)

GRUPOS_PAIS = {
    "Espana": [
        r'\bSPAIN\b', r'\bESPANA\b', r'\bESPA.A\b',
        r'(^|[, ])ES:', r'\|ES\b', r'\bES\s*:', r'ES\|'
    ],
    "Polonia": [
        r'\bPOLAND\b', r'\bPOLSKA\b', r'\bPOLISH\b',
        r'(^|[, ])PL:', r'\|PL\b', r'\bPL\s*:', r'PL\|'
    ],
    "United Kingdom": [
        r'\bUNITED KINGDOM\b', r'\bUK\b', r'\bENGLAND\b', r'\bBRITAIN\b',
        r'(^|[, ])UK:', r'(^|[, ])GB:', r'\|UK\b', r'\|GB\b', r'UK\|', r'GB\|'
    ],
    "Latino": [
        r'\bLATINO\b', r'\bLATAM\b', r'\bLATIN\b', r'\bMEXICO\b',
        r'\bARGENTINA\b', r'\bCOLOMBIA\b', r'\bCHILE\b', r'\bPERU\b', r'\bVENEZUELA\b'
    ],
}

ORDEN_ESPANA = [
    "LA 1", "LA 1 CANARIAS", "TVE 1", "LA1", "TVE1",
    "LA 2", "TVE 2", "LA2", "TVE2",
    "ANTENA 3", "ANTENA3",
    "CUATRO",
    "TELECINCO", "TELE 5", "TELE5",
    "LA SEXTA", "LASEXTA", "LA6",
    "CANAL 24 HORAS", "24 HORAS",
    "TELEDEPORTE", "CLAN",
    "NEOX", "NOVA", "MEGA", "ATRESERIES",
    "FDF", "FACTORIA DE FICCION", "DIVINITY", "ENERGY", "BE MAD", "BEMAD",
    "TRECE", "DMAX", "PARAMOUNT", "DISNEY CHANNEL",
    "DISCOVERY", "NATIONAL GEOGRAPHIC", "NAT GEO", "ODISEA", "HISTORY", "HISTORY CHANNEL",
    "AXN", "AXN WHITE", "CALLE 13", "SYFY", "WARNER", "COMEDY CENTRAL", "AMC", "FOX", "TCM",
    "EUROSPORT", "GOL PLAY", "GOL TV", "MOVISTAR"
]

ORDEN_POLONIA = [
    "TVP 1", "TVP 2", "TVP 3", "TVP",
    "TVN 24", "TVN7", "TVN",
    "POLSAT NEWS", "POLSAT SPORT", "POLSAT",
    "TTV", "TV4", "TV6"
]

ORDEN_UK = [
    "BBC ONE", "BBC TWO", "BBC THREE", "BBC FOUR", "BBC NEWS", "BBC",
    "ITV 1", "ITV 2", "ITV 3", "ITV 4", "ITV",
    "CHANNEL 4", "CHANNEL 5", "SKY NEWS", "SKY ONE", "SKY ATLANTIC", "SKY MAX", "SKY"
]

RE_GROUP = re.compile(r'(group-title=")[^"]*(")', re.IGNORECASE)

def limpiar_nombre_canal(extinf_line):
    if "," in extinf_line:
        encabezado, nombre = extinf_line.rsplit(",", 1)
    else:
        encabezado = ""
        nombre = extinf_line.strip()

    nombre_limpio = re.sub(r'^(ES|PL|UK|GB)(\||:|\s+|-)+', '', nombre.strip(), flags=re.IGNORECASE).strip()

    if encabezado:
        return f"{encabezado},{nombre_limpio}"
    return nombre_limpio

def normalizar_grupo(extinf_line, nombre_grupo):
    if RE_GROUP.search(extinf_line):
        return RE_GROUP.sub(r'\g<1>' + nombre_grupo + r'\g<2>', extinf_line, count=1)
    return extinf_line.replace('#EXTINF:-1', f'#EXTINF:-1 group-title="{nombre_grupo}"', 1)

def es_canal_en_vivo(url):
    url_lower = url.lower()
    if "/movie/" in url_lower or "/series/" in url_lower:
        return False
    if url_lower.endswith(('.mp4', '.mkv', '.avi', '.mp3', '.mov', '.flv')):
        return False
    return True

def obtener_categoria(extinf_line):
    texto = extinf_line.upper()

    # Redirigido a la categoría camuflada "Motor"
    if PATRON_ADULT.search(texto):
        return "Motor"

    if PATRON_F1.search(texto):
        return "F1"

    if PATRON_FUTBOL.search(texto):
        return "Futbol"

    for nombre_grupo, patrones in GRUPOS_PAIS.items():
        for patron in patrones:
            if re.search(patron, texto, re.IGNORECASE):
                return nombre_grupo

    return None

def obtener_peso_orden(extinf_line, lista_prioridades):
    if "," in extinf_line:
        nombre_canal = extinf_line.rsplit(",", 1)[1].strip()
    else:
        nombre_canal = extinf_line.strip()

    nombre_upper = nombre_canal.upper().strip()

    for indice, patron in enumerate(lista_prioridades):
        patron_upper = patron.upper()
        if nombre_upper == patron_upper:
            return indice
        if re.match(r'^' + re.escape(patron_upper) + r'(?:\s+(?:FHD|UHD|HD|SD|4K|HEVC))?$', nombre_upper):
            return indice

    return 999

def clave_duplicado(extinf_line):
    if "," in extinf_line:
        nombre = extinf_line.rsplit(",", 1)[1].strip()
    else:
        nombre = extinf_line.strip()

    nombre = re.sub(r'\s+', ' ', nombre)
    nombre = re.sub(r'\s+(FHD|UHD|HD|SD|4K|HEVC)\s*$', lambda m: " " + m.group(1).upper(), nombre, flags=re.IGNORECASE)
    return nombre.upper()

def eliminar_duplicados(canales_por_categoria):
    eliminados_total = 0
    for categoria, lista_canales in canales_por_categoria.items():
        vistos = set()
        canales_limpios = []
        for extinf, url, fuente in lista_canales:
            clave = clave_duplicado(extinf)
            if clave in vistos:
                eliminados_total += 1
                continue
            vistos.add(clave)
            canales_limpios.append((extinf, url, fuente))
        canales_por_categoria[categoria] = canales_limpios
    return eliminados_total

def procesar_respuesta(r, canales_por_categoria, contador_por_fuente, indice_fuente):
    pending_extinf = None
    total_extinf = total_urls = total_guardados = total_descartados = 0

    for raw_line in r.iter_lines():
        if not raw_line:
            continue
        try:
            line_str = raw_line.decode("utf-8").strip()
        except UnicodeDecodeError:
            line_str = raw_line.decode("latin-1", errors="replace").strip()

        if line_str.startswith("#EXTINF"):
            pending_extinf = line_str
            total_extinf += 1
            continue

        if line_str.startswith("#EXTVLCOPT"):
            continue

        if not line_str.startswith("#") and pending_extinf:
            total_urls += 1
            if es_canal_en_vivo(line_str):
                categoria = obtener_categoria(pending_extinf)
                if categoria in canales_por_categoria:
                    extinf_limpio = limpiar_nombre_canal(pending_extinf)
                    extinf_modificado = normalizar_grupo(extinf_limpio, categoria)
                    canales_por_categoria[categoria].append((extinf_modificado, line_str, indice_fuente))
                    total_guardados += 1
                else:
                    total_descartados += 1
            pending_extinf = None

    contador_por_fuente[indice_fuente] = {
        "extinf": total_extinf,
        "urls": total_urls,
        "guardados": total_guardados,
        "descartados": total_descartados,
    }

def filtrar():
    headers = {
        "User-Agent": "IPTVSmarters/3.1.5 (Linux; Android 11)",
        "Accept": "*/*",
    }

    canales_por_categoria = {
        "Espana": [],
        "Polonia": [],
        "United Kingdom": [],
        "Latino": [],
        "Futbol": [],
        "F1": [],
        "Motor": [],
    }

    contador_por_fuente = {}

    print("\n" + "=" * 65)
    print(" IPTV - PROCESANDO FUENTES ")
    print("=" * 65)

    for i, url_fuente in enumerate(FUENTES, start=1):
        print(f"\n--- FUENTE {i} ---")
        try:
            print(f"Descargando fuente {i}...")
            with requests.get(url_fuente, stream=True, timeout=(15, 300), headers=headers) as r:
                r.raise_for_status()
                print(f"HTTP Status: {r.status_code}")
                procesar_respuesta(r, canales_por_categoria, contador_por_fuente, i)

            datos = contador_por_fuente[i]
            print(f"EXTINF leidos:    {datos['extinf']}")
            print(f"URLs encontradas: {datos['urls']}")
            print(f"Canales guardados:{datos['guardados']}")
            print(f"Descartados:      {datos['descartados']}")

        except Exception as e:
            print(f"ERROR procesando fuente {i}: {e}")

    print("\nEliminando duplicados...")
    duplicados_eliminados = eliminar_duplicados(canales_por_categoria)
    print(f"Duplicados eliminados: {duplicados_eliminados}")

    canales_por_categoria["Espana"].sort(key=lambda c: (obtener_peso_orden(c[0], ORDEN_ESPANA), c[0].upper()))
    canales_por_categoria["Polonia"].sort(key=lambda c: (obtener_peso_orden(c[0], ORDEN_POLONIA), c[0].upper()))
    canales_por_categoria["United Kingdom"].sort(key=lambda c: (obtener_peso_orden(c[0], ORDEN_UK), c[0].upper()))

    total = 0
    print("\nEscribiendo lista final...")
    with open(ARCHIVO_SALIDA, "w", encoding="utf-8") as f:
        f.write("#EXTM3U\n")
        for categoria, lista_canales in canales_por_categoria.items():
            for extinf, url, fuente in lista_canales:
                f.write(extinf + "\n")
                f.write(url + "\n")
                total += 1

    print("\n" + "=" * 65)
    print("LISTA GENERADA CORRECTAMENTE")
    print(f"Archivo: {ARCHIVO_SALIDA}")
    print(f"Total de canales: {total}")
    print("=" * 65)

if __name__ == "__main__":
    filtrar()
