#!/usr/bin/env bash
# enumerate_subdomains
# --------------------
# Enumera subdominios de un dominio objetivo usando un diccionario integrado de
# ~100 subdominios comunes. Detecta tanto registros A (IP directa) como CNAME.
# Opcionalmente guarda el resultado en un archivo.
#
# USO (directo):
#   enumerate_subdomains <dominio> [archivo_salida]
#   enumerate_subdomains example.com
#   enumerate_subdomains example.com /tmp/resultado.txt
#
# Depende de: dig (dnsutils)

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../shell/bash_colors.sh"
source "$SCRIPT_DIR/../shell/bash_log.sh"
bash_colors
bash_log_init

# ─── Diccionario integrado ─────────────────────────────────────────────────────

_SUBDOMAIN_WORDLIST=(
    www mail ftp api dev admin vpn ssh git gitlab github jenkins ci cd
    staging prod test demo beta alpha app web portal intranet extranet
    remote desktop files cdn static assets media img images upload
    db database mysql postgres redis mongo smtp pop imap webmail mx
    ns1 ns2 dns autodiscover autoconfig crm erp shop store payment
    backup old legacy v1 v2 v3 internal corp office support helpdesk
    wiki docs doc status monitor grafana kibana elastic search
    registry docker k8s kubernetes auth sso login oauth api2 mobile
)

# ─── Funciones puras ──────────────────────────────────────────────────────────

_sub_is_valid_domain() {
    [[ -n "$1" && "$1" =~ ^[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}$ ]]
}

_sub_build_fqdn() {
    local sub="$1"
    local domain="$2"
    echo "${sub}.${domain}"
}

# ─── Funciones de efecto ──────────────────────────────────────────────────────

_sub_resolve_a() {
    local fqdn="$1"
    dig +short A "$fqdn" 2>/dev/null | grep -E '^[0-9]+\.' | head -1 || true
}

_sub_resolve_cname() {
    local fqdn="$1"
    dig +short CNAME "$fqdn" 2>/dev/null | head -1 || true
}

# ─── Punto de entrada ─────────────────────────────────────────────────────────

enumerate_subdomains() {
    local domain="$1"
    local output_file="${2:-}"

    if [[ -z "$domain" ]]; then
        error "enumerate_subdomains: se requiere un dominio como argumento" >&2
        return 1
    fi

    if ! _sub_is_valid_domain "$domain"; then
        error "enumerate_subdomains: dominio no válido: '$domain'" >&2
        return 1
    fi

    if ! command -v dig &>/dev/null; then
        error "enumerate_subdomains: 'dig' no está instalado (sudo apt install dnsutils)" >&2
        return 1
    fi

    local total="${#_SUBDOMAIN_WORDLIST[@]}"
    local found=0
    local checked=0

    info "Probando ${total} subdominios en ${domain}..."
    echo ""

    if [[ -n "$output_file" ]]; then
        echo "# Subdominios encontrados en ${domain} -- $(date)" > "$output_file"
    fi

    for sub in "${_SUBDOMAIN_WORDLIST[@]}"; do
        local fqdn
        fqdn="$(_sub_build_fqdn "$sub" "$domain")"
        checked=$((checked + 1))

        local ip
        ip="$(_sub_resolve_a "$fqdn")"

        if [[ -n "$ip" ]]; then
            echo -e "  ${GREEN}[ok]${NC} ${fqdn} -> ${CYAN}${ip}${NC}"
            [[ -n "$output_file" ]] && echo "${fqdn} -> ${ip}" >> "$output_file"
            found=$((found + 1))
        else
            local cname
            cname="$(_sub_resolve_cname "$fqdn")"
            if [[ -n "$cname" ]]; then
                echo -e "  ${YELLOW}[cn]${NC} ${fqdn} -> CNAME: ${cname}"
                [[ -n "$output_file" ]] && echo "${fqdn} -> CNAME: ${cname}" >> "$output_file"
                found=$((found + 1))
            fi
        fi

        # Progreso cada 20 subdominios
        if (( checked % 20 == 0 )); then
            echo -e "  ${DIM_GRAY}[${checked}/${total} probados, ${found} encontrados]${NC}"
        fi
    done

    echo ""
    echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"

    if [[ $found -eq 0 ]]; then
        info "No se encontraron subdominios en el diccionario"
    else
        success "Total encontrados: ${found} de ${total} probados"
        [[ -n "$output_file" ]] && info "Resultado guardado en: ${output_file}"
    fi

    echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"
}

# Ejecutar si se llama directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    enumerate_subdomains "$@"
fi
