"""Descarga de archivos en streaming — HTTP client sin dependencias externas."""

import os
import urllib.error
import urllib.request


def http_download_file(
    url: str,
    dest_path: str,
    headers: dict[str, str] | None = None,
    timeout: float = 120.0,
    chunk_size: int = 8192,
) -> dict:
    """Descarga un archivo por HTTP en streaming (sin cargar todo en memoria).

    Crea los directorios intermedios si no existen. Si el archivo destino
    ya existe lo sobreescribe. La descarga se hace en chunks para evitar
    consumo de memoria excesivo con archivos grandes.

    Args:
        url: URL del archivo a descargar.
        dest_path: Ruta local destino donde guardar el archivo.
        headers: Headers HTTP adicionales.
        timeout: Segundos maximo de espera para la conexion (default 120).
        chunk_size: Tamano de cada chunk en bytes (default 8192).

    Returns:
        dict con campos ``path`` (str), ``size_bytes`` (int) y
        ``content_type`` (str).

    Raises:
        RuntimeError: Si el status HTTP es >= 400.
    """
    req = urllib.request.Request(url, headers=headers or {}, method="GET")

    os.makedirs(os.path.dirname(os.path.abspath(dest_path)), exist_ok=True)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            content_type: str = resp.headers.get("Content-Type", "")
            size_bytes = 0
            with open(dest_path, "wb") as f:
                while True:
                    chunk = resp.read(chunk_size)
                    if not chunk:
                        break
                    f.write(chunk)
                    size_bytes += len(chunk)
    except urllib.error.HTTPError as e:
        short_url = url[:100] if len(url) > 100 else url
        raise RuntimeError(
            f"http_download_file: HTTP {e.code} at {short_url!r}"
        ) from e

    return {
        "path": dest_path,
        "size_bytes": size_bytes,
        "content_type": content_type,
    }
