import xml.etree.ElementTree as ET
import urllib.request
import urllib.parse
import json
import os
import glob
from datetime import datetime

# Detecta automáticamente la ruta absoluta del hosting
FOLDER_PATH = os.path.dirname(os.path.abspath(__file__))
LOG_PATH = os.path.join(FOLDER_PATH, "cron_log.txt")

def verificar_url(url):
    """Realiza una petición rápida para ver si el stream está vivo."""
    try:
        req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
        # SOLUCIÓN 2: Subimos el timeout a 10 segundos para dar más margen a streams lentos
        with urllib.request.urlopen(req, timeout=10) as response:
            return response.getcode() == 200
    except Exception:
        return False

def buscar_nueva_url(nombre_radio, country_filtro=None):
    """Busca un streaming alternativo aplicando filtros inteligentes de país."""
    try:
        nombre_busqueda = nombre_radio
        hint_parentesis = ""
        if "(" in nombre_radio and ")" in nombre_radio:
            partes = nombre_radio.split("(")
            nombre_busqueda = partes[0].strip()
            hint_parentesis = partes[1].replace(")", "").strip().lower()

        query = urllib.parse.quote(nombre_busqueda)
        api_url = f"https://de1.api.radio-browser.info/json/stations/search?name={query}&hidebroken=true"
        
        req = urllib.request.Request(api_url, headers={'User-Agent': 'BunAppsAutomator'})
        with urllib.request.urlopen(req, timeout=5) as response:
            resultados = json.loads(response.read().decode())
            
            for estacion in resultados:
                if estacion.get('lastcheckok') != 1 or not estacion.get('url_resolved'):
                    continue
                
                estacion_name = estacion.get('name', '').lower()
                estacion_country = estacion.get('country', '').lower()
                estacion_state = estacion.get('state', '').lower()
                
                if country_filtro:
                    cf_lower = country_filtro.lower()
                    if cf_lower not in estacion_country and cf_lower not in estacion_state and cf_lower not in estacion_name:
                        continue
                
                if hint_parentesis:
                    if hint_parentesis not in estacion_name and hint_parentesis not in estacion_country and hint_parentesis not in estacion_state:
                        continue
                
                nueva_url = estacion['url_resolved']
                if verificar_url(nueva_url):
                    return nueva_url
                    
    except Exception:
        return None
    return None

def ejecutar_mantenimiento_portafolio():
    ruta_busqueda = os.path.join(FOLDER_PATH, "**/*.xml")
    archivos_xml = glob.glob(ruta_busqueda, recursive=True)
    
    ahora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    cambios_realizados = []

    if not archivos_xml:
        with open(LOG_PATH, "a", encoding="utf-8") as log:
            log.write(f"[{ahora}] ALERTA: No se encontraron archivos XML en: {FOLDER_PATH}\n")
        return

    for xml_file in archivos_xml:
        nombre_archivo = os.path.basename(xml_file)
        nombre_carpeta = os.path.basename(os.path.dirname(xml_file)) 
        
        if nombre_carpeta == "radios" or nombre_archivo == "cron_log.txt" or nombre_archivo == "debug.log":
            continue
            
        try:
            tree = ET.parse(xml_file)
            root = tree.getroot()
            hubo_cambios = False

            for station in root.findall('.//station'):
                nombre = station.get('name')
                url_actual = station.get('link')
                country_filtro = station.get('country') 
                # SOLUCIÓN 3: Leer atributo opcional para ignorar auditoría
                skip_attr = station.get('skip_check') 

                if not nombre or not url_actual:
                    continue
                
                # REGLA DE OMISIÓN: Si el nombre incluye "(only for..." o tiene el atributo skip_check activo
                nombre_lower = nombre.lower()
                es_geobloqueada = "only for" in nombre_lower or "vpn" in nombre_lower
                
                if skip_attr == "true" or es_geobloqueada:
                    # Se salta la verificación de red de esta radio de forma segura
                    continue
                
                if not verificar_url(url_actual):
                    nueva_url = buscar_nueva_url(nombre, country_filtro)
                    
                    if nueva_url:
                        station.set('link', nueva_url)
                        hubo_cambios = True
                        cambios_realizados.append(f"✓ [{nombre_carpeta}/{nombre_archivo}] Reparada: {nombre} -> {nueva_url}")
                    else:
                        cambios_realizados.append(f"✗ [{nombre_carpeta}/{nombre_archivo}] CAÍDA SIN REEMPLAZO SEGURO: {nombre}")

            if hubo_cambios:
                tree.write(xml_file, encoding="utf-8", xml_declaration=True)

        except Exception as e:
            cambios_realizados.append(f"⚠ Error en {nombre_carpeta}/{nombre_archivo}: {str(e)}")

    with open(LOG_PATH, "a", encoding="utf-8") as log:
        log.write(f"[{ahora}] --- Ejecución del Cron realizada ---\n")
        if cambios_realizados:
            for cambio in cambios_realizados:
                log.write(cambio + "\n")
        else:
            log.write("-> Todos los enlaces están estables o filtrados de forma segura.\n")

if __name__ == "__main__":
    ejecutar_mantenimiento_portafolio()