"""Enumeracion OSINT pasiva de subdominios via Certificate Transparency (crt.sh).

Funcion IMPURA: consulta los logs publicos de Certificate Transparency a
traves de crt.sh y extrae los subdominios que han aparecido en certificados
emitidos para el dominio. Es OSINT pasivo: no toca al dominio objetivo, solo
consulta registros CT publicos.
"""

import os
import sys

sys.path.insert(
    0, os.path.join(os.path.dirname(__file__), "..", "..", "functions")
)

from infra.http_get_json import http_get_json  # noqa: E402


def enum_subdomains_crtsh(dominio: str, timeout_s: float = 20.0) -> list:
    """Enumera subdominios de un dominio desde Certificate Transparency.

    Consulta ``https://crt.sh/?q=%25.<dominio>&output=json`` (``%25`` = ``%``,
    el wildcard de crt.sh) usando ``http_get_json`` del registry. crt.sh
    devuelve un array JSON de certificados; de cada uno se toma el campo
    ``name_value`` (que puede contener varios nombres separados por saltos de
    linea, uno por SAN). Se separan, deduplican, se filtran los wildcards
    (``*.``) y se devuelve la lista ordenada de subdominios unicos.

    Args:
        dominio: Dominio base a enumerar (ej. ``"organic-machine.com"``).
        timeout_s: Segundos maximo de espera de la peticion HTTP (default 20).

    Returns:
        Lista ordenada de subdominios unicos (sin wildcards). Lista vacia si
        crt.sh no devuelve resultados.

    Raises:
        RuntimeError: Si el dominio esta vacio o la peticion HTTP falla.
    """
    if not dominio or not dominio.strip():
        raise RuntimeError("enum_subdomains_crtsh: dominio vacio")

    dom = dominio.strip().lower()
    # %25 es el wildcard '%' de crt.sh: busca cualquier nombre que termine en .<dominio>
    url = f"https://crt.sh/?q=%25.{dom}&output=json"

    data = http_get_json(url, timeout=timeout_s)

    if not isinstance(data, list):
        raise RuntimeError(
            f"enum_subdomains_crtsh: respuesta crt.sh inesperada "
            f"(tipo {type(data).__name__})"
        )

    found: set = set()
    for cert in data:
        if not isinstance(cert, dict):
            continue
        name_value = cert.get("name_value", "")
        for raw_name in name_value.split("\n"):
            name = raw_name.strip().lower()
            if not name:
                continue
            if name.startswith("*."):
                continue
            found.add(name)

    return sorted(found)
