import httpx
from urllib.parse import urljoin

from hermes_hls_security import validar_destino

MAX_MANIFEST = 1024 * 1024
MAX_SEGMENT = 20 * 1024 * 1024

def descargar_hls(url, tipo="manifest"):
    limite = MAX_MANIFEST if tipo == "manifest" else MAX_SEGMENT

    actual = validar_destino(url)

    with httpx.Client(
        timeout=15,
        follow_redirects=False,
        trust_env=False
    ) as cliente:

        for _ in range(4):
            validar_destino(actual)

            with cliente.stream("GET", actual) as respuesta:

                if respuesta.status_code in (301, 302, 303, 307, 308):
                    destino = respuesta.headers.get("location")

                    if not destino:
                        raise ValueError("Redireccion sin destino")

                    actual = validar_destino(urljoin(actual, destino))
                    continue

                respuesta.raise_for_status()

                longitud = respuesta.headers.get("content-length")
                if longitud and int(longitud) > limite:
                    raise ValueError("Recurso demasiado grande")

                contenido = bytearray()

                for bloque in respuesta.iter_bytes(65536):
                    contenido.extend(bloque)

                    if len(contenido) > limite:
                        raise ValueError("Limite de descarga excedido")

                return {
                    "contenido": bytes(contenido),
                    "url_final": actual,
                    "tipo": respuesta.headers.get(
                        "content-type", "application/octet-stream"
                    )
                }

    raise ValueError("Demasiadas redirecciones")


def transmitir_segmento(url):
    """
    Generador HLS.
    Valida cada destino y transmite bloques de video
    sin almacenar el segmento completo en memoria.
    """
    actual = validar_destino(url)
    total = 0

    with httpx.Client(
        timeout=httpx.Timeout(20.0, connect=5.0),
        follow_redirects=False,
        trust_env=False
    ) as cliente:

        for _ in range(4):
            validar_destino(actual)

            with cliente.stream("GET", actual) as respuesta:

                if respuesta.status_code in (301, 302, 303, 307, 308):
                    destino = respuesta.headers.get("location")

                    if not destino:
                        raise ValueError("Redireccion sin destino")

                    actual = validar_destino(
                        urljoin(actual, destino)
                    )
                    continue

                respuesta.raise_for_status()

                longitud = respuesta.headers.get("content-length")

                if longitud and int(longitud) > MAX_SEGMENT:
                    raise ValueError("Segmento demasiado grande")

                for bloque in respuesta.iter_bytes(65536):
                    total += len(bloque)

                    if total > MAX_SEGMENT:
                        raise ValueError(
                            "Limite de segmento excedido"
                        )

                    yield bloque

                return

    raise ValueError("Demasiadas redirecciones")
