import httpx
from urllib.parse import urlsplit
from fastapi import APIRouter, HTTPException
from fastapi.responses import Response, StreamingResponse
from starlette.concurrency import run_in_threadpool

from hermes_hls_registry_v2 import HLSRegistryV2
from hermes_hls_manifest import transformar_manifest
from hermes_hls_manifest_v4_lab import transformar_manifest_v4
from hermes_hls_fetch import descargar_hls
from hermes_hls_stream_v3 import preparar_segmento, transmitir_preparado
from hermes_hls_security import validar_destino
from hermes_player_gateway import resolver_canal

router = APIRouter(prefix="/api/player")
registro = HLSRegistryV2(ttl=600)


def registrar(url, identidad, canal):
    url = validar_destino(url)

    clave = (canal, identidad)
    token = registro.registrar(url, clave)

    return "/api/player/resource/" + token


async def responder(url, canal):
    url = validar_destino(url)

    if not urlsplit(url).path.endswith(".m3u8"):
        cliente, respuesta = await preparar_segmento(url)

        return StreamingResponse(
            transmitir_preparado(cliente, respuesta),
            media_type="video/mp2t",
            headers={"Cache-Control": "no-store"}
        )

    resultado = await run_in_threadpool(
        descargar_hls, url, "manifest"
    )

    contenido = resultado["contenido"]
    origen = resultado["url_final"]

    if not contenido.startswith(b"#EXTM3U"):
        raise ValueError("Manifiesto HLS invalido")

    texto = contenido.decode("utf-8-sig")

    if "#EXT-X-MEDIA-SEQUENCE:" in texto:
        transformado = transformar_manifest_v4(
            texto,
            origen,
            lambda u, i: registrar(u, ("segmento", i), canal),
            canal
        )
    else:
        transformado = transformar_manifest(
            texto,
            origen,
            lambda u: registrar(u, ("manifest", u), canal)
        )

    return Response(
        content=transformado,
        media_type="application/vnd.apple.mpegurl",
        headers={"Cache-Control": "no-store"}
    )


@router.get("/play/{liga}/{equipo}.m3u8")
async def reproducir(liga: str, equipo: str):
    if not liga.isalnum() or not equipo.isalnum():
        raise HTTPException(
            status_code=400,
            detail="Canal invalido"
        )

    try:
        url = await run_in_threadpool(
            resolver_canal, liga, equipo
        )
        return await responder(url, liga + "/" + equipo)

    except Exception:
        raise HTTPException(
            status_code=502,
            detail="No se pudo iniciar reproduccion"
        )


@router.get("/resource/{identificador}")
async def recurso(identificador: str):
    try:
        url = registro.resolver(identificador)
        identidad = registro.recursos[identificador]["identidad"]
        canal = identidad[0]

    except (ValueError, KeyError):
        raise HTTPException(
            status_code=404,
            detail="Recurso no disponible"
        )

    try:
        return await responder(url, canal)

    except httpx.HTTPStatusError:
        raise HTTPException(
            status_code=502,
            detail="Origen HLS no disponible"
        )

    except Exception:
        raise HTTPException(
            status_code=502,
            detail="Error al recuperar recurso"
        )
