import os,re,base64,urllib.request,sqlite3
from urllib.parse import urlsplit
def consultar_sling_futbol(termino):
    if not isinstance(termino,str) or not 3<=len(termino.strip())<=100: raise ValueError('Término inválido')
    user=os.environ.get('HERMES_O11_USER','')
    password=os.environ.get('HERMES_O11_PASSWORD','')
    if not user or not password: return {'error':'CREDENCIALES_NO_CARGADAS'}
    auth=base64.b64encode((user+':'+password).encode()).decode()
    req=urllib.request.Request('http://15.204.47.5:1234/playlist.m3u',headers={'Authorization':'Basic '+auth,'User-Agent':'Hermes-V3C'})
    with urllib.request.urlopen(req,timeout=25) as response: content=response.read(25*1024*1024+1)
    if len(content)>25*1024*1024: raise ValueError('M3U demasiado grande')
    channels={}
    name=''
    for line in content.decode('utf-8-sig',errors='replace').splitlines():
        line=line.strip()
        if line.startswith('#EXTINF'): name=line.rsplit(',',1)[-1].strip()
        elif line.startswith('http') and name:
            m=re.search(r'vix\s*(?:premium\s*)?deportes\s*(\d+)',name,re.I)
            p=urlsplit(line)
            if m and p.scheme=='http' and p.hostname=='15.204.47.5' and p.port==1234 and p.path.startswith('/stream/sling/') and not p.username and not p.password:
                channels.setdefault(int(m.group(1)),set()).add(name)
            name=''
    with sqlite3.connect('file:/var/lib/hermes-nexus/epg.db?mode=ro',uri=True) as db:
        rows=db.execute("SELECT canal,titulo,inicio,fin FROM epg_programas WHERE fuente='sling' AND LOWER(titulo) LIKE ? ORDER BY inicio DESC LIMIT 40",('%'+termino.lower()+'%',)).fetchall()
    result=[]
    for canal,titulo,inicio,fin in rows:
        m=re.search(r'vix(?:premium)?deportes(\d+)',canal,re.I)
        if not m: continue
        names=channels.get(int(m.group(1)),set())
        result.append({'canal':canal,'titulo':titulo,'inicio':inicio,'fin':fin,'catalogo_coincidencias':len(names),'estado':'CANDIDATO' if len(names)==1 else 'REVISAR'})
    return {'programas':result[:15],'catalogo_descargado':True,'guardado':False,'online_verificado':False,'confirmacion_publica':False,'nota':'Solo propuesta; comprobar nombres de ambos equipos, horario y fuente pública antes de guardar.'}
