#!/usr/bin/env bash
# check_firewall
# --------------
# Detecta el firewall activo del sistema (ufw, firewalld o iptables) y muestra
# su estado y reglas. También lista los puertos en escucha para cruzar con reglas.
#
# USO (directo):
#   check_firewall
#
# Depende de: ufw, firewall-cmd o iptables (el que esté disponible), ss

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

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

_fw_detect() {
    if command -v ufw &>/dev/null && ufw status 2>/dev/null | grep -q "Status:"; then
        echo "ufw"
    elif command -v firewall-cmd &>/dev/null && firewall-cmd --state 2>/dev/null | grep -q "running"; then
        echo "firewalld"
    elif command -v iptables &>/dev/null; then
        echo "iptables"
    else
        echo "none"
    fi
}

_fw_ufw_is_active() {
    ufw status 2>/dev/null | grep -q "Status: active"
}

_fw_firewalld_is_running() {
    firewall-cmd --state 2>/dev/null | grep -q "running"
}

_fw_iptables_has_rules() {
    local count
    count="$(iptables -L INPUT --line-numbers 2>/dev/null | grep -c "^[0-9]" || echo 0)"
    [[ "$count" -gt 0 ]]
}

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

_fw_show_ufw() {
    echo -e "${PURPLE}════════ UFW ════════════════════════════════════${NC}"
    echo ""

    if _fw_ufw_is_active; then
        success "UFW está activo"
    else
        echo -e "  ${RED}[x]${NC} UFW está INACTIVO"
    fi

    echo ""
    info "Reglas activas:"
    ufw status verbose 2>/dev/null | while IFS= read -r line; do
        echo -e "  ${DIM_GRAY}${line}${NC}"
    done

    echo ""
}

_fw_show_firewalld() {
    echo -e "${PURPLE}════════ FirewallD ══════════════════════════════${NC}"
    echo ""

    if _fw_firewalld_is_running; then
        success "firewalld está activo"
    else
        echo -e "  ${RED}[x]${NC} firewalld está INACTIVO"
    fi

    echo ""
    local zone
    zone="$(firewall-cmd --get-default-zone 2>/dev/null || echo "desconocida")"
    info "Zona por defecto: ${zone}"
    echo ""

    info "Servicios permitidos en zona ${zone}:"
    firewall-cmd --zone="$zone" --list-services 2>/dev/null \
        | tr ' ' '\n' | while IFS= read -r svc; do
            echo -e "  ${GREEN}*${NC} ${svc}"
        done

    echo ""
    info "Puertos permitidos:"
    firewall-cmd --zone="$zone" --list-ports 2>/dev/null \
        | tr ' ' '\n' | while IFS= read -r port; do
            [[ -n "$port" ]] && echo -e "  ${YELLOW}*${NC} ${port}"
        done || true

    echo ""
}

_fw_show_iptables() {
    echo -e "${PURPLE}════════ iptables ═══════════════════════════════${NC}"
    echo ""

    for chain in INPUT OUTPUT FORWARD; do
        echo -e "${CYAN}── ${chain} ──${NC}"
        iptables -L "$chain" --line-numbers -n 2>/dev/null \
            | while IFS= read -r line; do echo -e "  ${DIM_GRAY}${line}${NC}"; done
        echo ""
    done

    if ! _fw_iptables_has_rules; then
        echo -e "  ${YELLOW}[!]${NC} No hay reglas INPUT definidas -- el sistema puede estar sin filtrar tráfico"
    fi
}

_fw_show_none() {
    echo ""
    echo -e "  ${RED}[x]${NC} No se detectó ningún firewall activo (ufw, firewalld, iptables)"
    echo -e "  ${YELLOW}[!]${NC} El sistema puede estar completamente expuesto"
    echo ""
    info "Para instalar y activar ufw: sudo apt install ufw && sudo ufw enable"
}

_fw_show_listening_crosscheck() {
    echo ""
    echo -e "${PURPLE}════════ Puertos en escucha (para cruzar con reglas) ════${NC}"
    echo ""
    ss -tlnp 2>/dev/null | tail -n +2 | while IFS= read -r line; do
        echo -e "  ${DIM_GRAY}${line}${NC}"
    done
}

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

check_firewall() {
    local fw
    fw="$(_fw_detect)"

    info "Firewall detectado: ${fw}"
    echo ""

    case "$fw" in
        ufw)       _fw_show_ufw ;;
        firewalld) _fw_show_firewalld ;;
        iptables)  _fw_show_iptables ;;
        none)      _fw_show_none ;;
    esac

    _fw_show_listening_crosscheck
}

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