import httpx
import uvicorn
import os
import secrets
import time
import json
import psutil
from typing import List
from fastapi import FastAPI, HTTPException, Depends, Request
from fastapi.responses import RedirectResponse, HTMLResponse, PlainTextResponse
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from apscheduler.schedulers.background import BackgroundScheduler
from pydantic import BaseModel

app = FastAPI()
security = HTTPBasic()

# --- ARCHIVO DE SEGURIDAD (WHITELIST) ---
SECURITY_FILE = os.path.join(os.path.dirname(__file__), "security.json")

def cargar_seguridad():
    if os.path.exists(SECURITY_FILE):
        try:
            with open(SECURITY_FILE, "r") as f:
                return json.load(f)
        except:
            pass
    return {"enabled": False, "ips": []}

def guardar_seguridad(data):
    with open(SECURITY_FILE, "w") as f:
        json.dump(data, f)

security_config = cargar_seguridad()

class SecurityModel(BaseModel):
    enabled: bool
    ips: List[str]

# --- CREDENCIALES TELEGRAM ---
TELEGRAM_BOT_TOKEN = "8287241319:AAHrtt6ja1LbxkoB8HRznABECLnXHM7T0zY"
TELEGRAM_CHAT_ID = "1797735602"

def enviar_alerta_telegram(mensaje):
    try:
        url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
        payload = {'chat_id': TELEGRAM_CHAT_ID, 'text': f"🏈 <b>Alerta del Panel NFL</b>\n\n{mensaje}", 'parse_mode': 'HTML'}
        httpx.post(url, data=payload, timeout=5.0)
    except Exception as e:
        print(f"[ERROR] No se pudo enviar Telegram: {e}")

def verificar_credenciales(credentials: HTTPBasicCredentials = Depends(security)):
    usuario_correcto = secrets.compare_digest(credentials.username, "Zeus")
    pass_correcto = secrets.compare_digest(credentials.password, "Laloekmj232023")
    if not (usuario_correcto and pass_correcto):
        raise HTTPException(status_code=401, detail="Acceso denegado", headers={"WWW-Authenticate": "Basic"})
    return credentials.username

# --- VARIABLES GLOBALES ---
last_net_io = psutil.net_io_counters()
last_net_time = time.time()

ESPN_STREAM = "http://51.81.107.170:7070/stream/hulumiami/espn/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"
NBC_STREAM = "http://51.81.107.170:7070/stream/hulumiami/wtvj/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"
NFL_NETWORK_STREAM = "http://15.204.107.193:7070/stream/huluatlanta/nflnetwork/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"

STREAM_DATABASE = {
    "cardinals": {"abbr": "ari", "CBS": "http://15.204.107.193:7070/stream/huluphoenix/kpho/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://23.237.34.58:7070/stream/huluphoenix/ksaz/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b"},
    "falcons": {"abbr": "atl", "CBS": "http://15.204.107.193:7070/stream/huluatlanta/wupa/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluatlanta/waga/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "ravens": {"abbr": "bal", "CBS": "http://15.204.107.193:7070/stream/hulubaltimore/wjz/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulubaltimore/wbff/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "bills": {"abbr": "buf", "CBS": "http://15.204.107.193:7070/stream/hulubuffalo/wivb/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulubuffalo/wutv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "panthers": {"abbr": "car", "CBS": "http://15.204.107.193:7070/stream/hulucharlotte/wbtv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulucharlotte/wjzy/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "bears": {"abbr": "chi", "CBS": "http://51.81.107.170:7070/stream/huluchicago/wbbm/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f", "FOX": "http://51.81.107.170:7070/stream/huluchicago/wfld/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "bengals": {"abbr": "cin", "CBS": "http://15.204.107.193:7070/stream/hulucincinnati/wkrc/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulucincinnati/wxix/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "browns": {"abbr": "cle", "CBS": "http://15.204.107.193:7070/stream/hulucleveland/woio/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulucleveland/wjw/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "cowboys": {"abbr": "dal", "CBS": "http://23.237.34.58:7070/stream/huludallas/ktvt/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b", "FOX": "http://147.135.104.121:1234/stream/huludallas/kdfw/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de"},
    "broncos": {"abbr": "den", "CBS": "http://15.204.107.193:7070/stream/huludenver/kcnc/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huludenver/kdvr/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "lions": {"abbr": "det", "CBS": "http://15.204.107.193:7070/stream/huludetroit/wwj/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huludetroit/wjbk/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "packers": {"abbr": "gb", "CBS": "http://15.204.107.193:7070/stream/hulugreenbay/wfrv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulugreenbay/wfrv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "texans": {"abbr": "hou", "CBS": "http://15.204.107.193:7070/stream/huluhouston/khou/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluhouston/kriv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "colts": {"abbr": "ind", "CBS": "http://15.204.107.193:7070/stream/huluindianapolis/wttv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluindianapolis/wxin/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "jaguars": {"abbr": "jax", "CBS": "http://15.204.107.193:7070/stream/hulujacksonville/wjax/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulujacksonville/wfox/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "chiefs": {"abbr": "kc", "CBS": "http://15.204.107.193:7070/stream/huluwichita/kwch/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluwichita/ksas/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "raiders": {"abbr": "lv", "CBS": "http://147.135.104.121:1234/stream/hululasvegas/klas/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de", "FOX": "http://51.81.107.170:7070/stream/hululasvegas/kvvu/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "rams": {"abbr": "lar", "CBS": "http://15.204.107.193:7070/stream/hulula/kcbs/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://23.237.34.58:7070/stream/hulula/kttv/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b"},
    "chargers": {"abbr": "lac", "CBS": "http://15.204.107.193:7070/stream/hulula/kcbs/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://23.237.34.58:7070/stream/hulula/kttv/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b"},
    "dolphins": {"abbr": "mia", "CBS": "http://23.237.34.58:7070/stream/hulumiami/wfor/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b", "FOX": "http://147.135.104.121:1234/stream/hulumiami/wsvn/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de"},
    "vikings": {"abbr": "min", "CBS": "http://15.204.107.193:7070/stream/huluminneapolis/wcco/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluminneapolis/kmsp/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "titans": {"abbr": "ten", "CBS": "http://15.204.107.193:7070/stream/hulunashville/wtvf/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulunashville/wztv/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "patriots": {"abbr": "ne", "CBS": "http://15.204.107.193:7070/stream/huluboston/wbz/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://51.81.107.170:7070/stream/huluboston/wfxt/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "saints": {"abbr": "no", "CBS": "http://15.204.107.193:7070/stream/huluneworleans/wwl/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://51.81.107.170:7070/stream/huluneworleans/wvue/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "giants": {"abbr": "nyg", "CBS": "http://15.204.107.193:7070/stream/hulunuevayork/wcbs/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://51.81.107.170:7070/stream/hulunuevayork/wnyw/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "jets": {"abbr": "nyj", "CBS": "http://15.204.107.193:7070/stream/hulunuevayork/wcbs/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://51.81.107.170:7070/stream/hulunuevayork/wnyw/master.m3u8?u=admin&p=9b70e03097fa174868df37b951b40959fe67e648dcd5f9c5c346e9873b48597f"},
    "eagles": {"abbr": "phi", "CBS": "http://15.204.107.193:7070/stream/huluphili/kyw/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://147.135.104.121:1234/stream/huluphili/wtxf/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de"},
    "steelers": {"abbr": "pit", "CBS": "http://15.204.107.193:7070/stream/hulupittsburgh/kdka/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulupittsburgh/wpgh/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "49ers": {"abbr": "sf", "CBS": "http://15.204.107.193:7070/stream/hulusanfrancisco/kpix/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/hulusanfrancisco/ktvu/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "seahawks": {"abbr": "sea", "CBS": "http://15.204.107.193:7070/stream/huluseattle/kiro/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://15.204.107.193:7070/stream/huluseattle/kcpq/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd"},
    "buccaneers": {"abbr": "tb", "CBS": "http://15.204.107.193:7070/stream/hulutampa/wtsp/master.m3u8?u=admin&p=5f797969be6d73acfc4b2456701fe5269ac6b62ed7745a0890a2397e0d1c6ddd", "FOX": "http://23.237.34.58:7070/stream/hulutampa/wtvt/master.m3u8?u=admin&p=99dfdd1ac82f455c4de1572a9eca98c29392199d1cd5a912b6cc36f53de8848b"},
    "commanders": {"abbr": "was", "CBS": "http://147.135.104.121:1234/stream/huluwashington/wusa/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de", "FOX": "http://147.135.104.121:1234/stream/huluwashington/wttg/master.m3u8?u=admin&p=8366d2f479ee25eaecd01b42960c3fe667ac6f49f2fb41d7c236fde115bd64de"}
}

current_game_info = {}
manual_overrides = {}
active_viewers = {}

class OverrideModel(BaseModel):
    team: str
    url: str

def clean_old_viewers():
    now = time.time()
    for team, ips in list(active_viewers.items()):
        active_viewers[team] = {ip: data for ip, data in ips.items() if now - data["time"] < 500}

def sync_schedule():
    global current_game_info
    url = "https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard"
    try:
        resp = httpx.get(url, timeout=10)
        data = resp.json()
        mapping = {}
        for event in data.get("events", []):
            status = event.get("status", {}).get("type", {}).get("state", "pre")
            competition = event["competitions"][0]
            broadcast = ""
            if competition.get("broadcasts"):
                broadcast = " ".join(competition["broadcasts"][0].get("names", [])).upper()
            
            for competitor in competition.get("competitors", []):
                slug = competitor["team"]["name"].lower().replace(" ", "")
                mapping[slug] = {
                    "network": broadcast,
                    "match_name": event.get("shortName", ""),
                    "match_date": event.get("date", ""),
                    "state": status
                }
        current_game_info = mapping
    except Exception:
        pass

def auditar_juegos_prime():
    equipos_afectados = []
    for slug, info in current_game_info.items():
        network = info.get("network", "")
        if ("PRIME" in network or "AMAZON" in network) and not manual_overrides.get(slug):
            equipos_afectados.append(slug.upper())
            
    if equipos_afectados:
        mensaje = (
            "⚠️ <b>RECORDATORIO DE JUEGOS PRIME</b> ⚠️\n\n"
            "El sistema detectó que hoy se transmitirá <i>Thursday Night Football</i> "
            "exclusivo por Amazon Prime.\n\n"
            "Los siguientes equipos <b>NO</b> tienen un Link Maestro asignado aún:\n"
            f"👉 <b>{', '.join(equipos_afectados)}</b>\n\n"
            "Entra al panel del Router NFL y coloca tu enlace en el campo 'Forzar Link Manual' para evitar caídas."
        )
        enviar_alerta_telegram(mensaje)

scheduler = BackgroundScheduler(timezone="America/Tijuana")
scheduler.add_job(sync_schedule, 'interval', minutes=2)
scheduler.add_job(clean_old_viewers, 'interval', seconds=30)
scheduler.add_job(auditar_juegos_prime, 'cron', day_of_week='thu', hour=10, minute=0)
scheduler.start()

@app.on_event("startup")
def startup_event():
    sync_schedule()

def obtener_url_asignada(team_slug):
    if manual_overrides.get(team_slug): return manual_overrides[team_slug]
    info = current_game_info.get(team_slug, {})
    network = info.get("network", "")
    data = STREAM_DATABASE.get(team_slug, {})
    
    if "NBC" in network: return NBC_STREAM
    if "ESPN" in network or "ABC" in network: return ESPN_STREAM
    if "NFL" in network: return NFL_NETWORK_STREAM
    if "CBS" in network: return data.get("CBS")
    if "FOX" in network: return data.get("FOX")
    return data.get("CBS")

@app.get("/")
def show_panel(username: str = Depends(verificar_credenciales)):
    html_path = os.path.join(os.path.dirname(__file__), "panel.html")
    try:
        with open(html_path, "r", encoding="utf-8") as f:
            return HTMLResponse(content=f.read())
    except:
        return HTMLResponse(content="<h1>Falta panel.html</h1>")

@app.get("/api/system")
def get_system_stats(username: str = Depends(verificar_credenciales)):
    global last_net_io, last_net_time
    current_net_io = psutil.net_io_counters()
    current_time = time.time()
    
    time_diff = current_time - last_net_time
    if time_diff > 0:
        bytes_sent = current_net_io.bytes_sent - last_net_io.bytes_sent
        bytes_recv = current_net_io.bytes_recv - last_net_io.bytes_recv
        tx_mbps = (bytes_sent * 8) / (1024 * 1024 * time_diff)
        rx_mbps = (bytes_recv * 8) / (1024 * 1024 * time_diff)
    else:
        tx_mbps = 0.0
        rx_mbps = 0.0
        
    last_net_io = current_net_io
    last_net_time = current_time

    cpu = psutil.cpu_percent(interval=None)
    ram = psutil.virtual_memory()
    
    return {
        "cpu_percent": cpu,
        "ram_percent": ram.percent,
        "ram_used_gb": round(ram.used / (1024**3), 2),
        "ram_total_gb": round(ram.total / (1024**3), 2),
        "tx_mbps": round(tx_mbps, 2),
        "rx_mbps": round(rx_mbps, 2)
    }

@app.get("/api/status")
def get_status(username: str = Depends(verificar_credenciales)):
    equipos_data = []
    for slug, data in STREAM_DATABASE.items():
        info = current_game_info.get(slug, {})
        equipos_data.append({
            "slug": slug,
            "logo": f"https://a.espncdn.com/i/teamlogos/nfl/500/{data['abbr']}.png",
            "assigned_url": obtener_url_asignada(slug),
            "manual_url": manual_overrides.get(slug, ""),
            "viewers": len(active_viewers.get(slug, {})),
            "network": info.get("network", ""),
            "match_name": info.get("match_name", ""),
            "match_date": info.get("match_date", ""),
            "state": info.get("state", "pre")
        })
    return {"equipos": equipos_data}

@app.get("/api/monitor")
def get_monitor(username: str = Depends(verificar_credenciales)):
    return active_viewers

@app.get("/api/security")
def get_sec(username: str = Depends(verificar_credenciales)):
    return security_config

@app.post("/api/security")
def update_sec(data: SecurityModel, username: str = Depends(verificar_credenciales)):
    global security_config
    security_config["enabled"] = data.enabled
    security_config["ips"] = [ip.strip() for ip in data.ips if ip.strip()]
    guardar_seguridad(security_config)
    return {"status": "ok"}

@app.post("/api/override")
def set_override(data: OverrideModel, username: str = Depends(verificar_credenciales)):
    if data.url.strip(): manual_overrides[data.team] = data.url.strip()
    else: manual_overrides.pop(data.team, None)
    return {"status": "ok"}

@app.get("/api/check")
async def check_stream(url: str, username: str = Depends(verificar_credenciales)):
    try:
        async with httpx.AsyncClient(verify=False) as client:
            resp = await client.get(url, timeout=7.0)
            if resp.status_code == 200: return {"status": "online"}
            return {"status": "offline"}
    except: return {"status": "offline"}

@app.get("/download/playlist.m3u")
def download_playlist(request: Request, username: str = Depends(verificar_credenciales)):
    host = request.headers.get("host", "51.81.243.2:8005")
    lines = ["#EXTM3U"]
    for slug, data in STREAM_DATABASE.items():
        logo_url = f"https://a.espncdn.com/i/teamlogos/nfl/500/{data['abbr']}.png"
        lines.append(f'#EXTINF:-1 tvg-id="{slug}" tvg-logo="{logo_url}" group-title="NFL VIP",NFL {slug.upper()}')
        lines.append(f"http://{host}/live/{slug}.m3u8")
    return PlainTextResponse("\n".join(lines), headers={"Content-Disposition": "attachment; filename=nfl_master_list.m3u"})

@app.get("/live/{team}.m3u8")
@app.get("/live/{team}.ts")
async def resolve_team_stream(team: str, request: Request):
    client_ip = request.client.host
    
    # 🔒 BLOQUEO POR WHITELIST 🔒
    if security_config.get("enabled"):
        if client_ip not in security_config.get("ips", []):
            raise HTTPException(status_code=403, detail="Acceso Denegado: IP no autorizada en Whitelist")
            
    team_slug = team.lower().replace("-", "").strip()
    if team_slug not in STREAM_DATABASE: raise HTTPException(status_code=404, detail="Equipo no encontrado")
    
    user_agent = request.headers.get("user-agent", "Desconocido")
    if team_slug not in active_viewers: active_viewers[team_slug] = {}
    active_viewers[team_slug][client_ip] = {
        "time": time.time(),
        "user_agent": user_agent
    }
    
    target = obtener_url_asignada(team_slug)
    if not target: target = STREAM_DATABASE[team_slug].get("CBS")
    return RedirectResponse(url=target, status_code=302)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8005)
