#!/usr/bin/env bash
# port_kill — Mata los procesos que escuchan en un puerto TCP dado.

port_kill() {
    local port="${1:-}"
    local signal="${2:-TERM}"

    # Validar puerto
    if [[ -z "$port" ]] || ! [[ "$port" =~ ^[0-9]+$ ]] || (( port < 1 || port > 65535 )); then
        echo "ERROR: puerto invalido: '$port' (debe ser 1-65535)" >&2
        return 2
    fi

    # Verificar herramienta disponible
    local tool=""
    if command -v lsof &>/dev/null; then
        tool="lsof"
    elif command -v fuser &>/dev/null; then
        tool="fuser"
    else
        echo "ERROR: se requiere lsof o fuser (ninguno disponible)" >&2
        return 5
    fi

    # Obtener PIDs
    local pids=()
    if [[ "$tool" == "lsof" ]]; then
        mapfile -t pids < <(lsof -ti "tcp:${port}" -sTCP:LISTEN 2>/dev/null)
    else
        mapfile -t pids < <(fuser -n tcp "${port}" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+$')
    fi

    if (( ${#pids[@]} == 0 )); then
        echo "NO_PROCESS port=${port}"
        return 0
    fi

    # Matar cada PID
    local permission_denied=0
    for pid in "${pids[@]}"; do
        [[ -z "$pid" ]] && continue
        if kill "-${signal}" "$pid" 2>/dev/null; then
            echo "KILLED pid=${pid} signal=${signal} port=${port}"
        else
            echo "PERMISSION_DENIED pid=${pid}" >&2
            permission_denied=1
        fi
    done

    if (( permission_denied )); then
        return 4
    fi

    # Esperar 2s y verificar
    sleep 2
    local remaining=()
    if [[ "$tool" == "lsof" ]]; then
        mapfile -t remaining < <(lsof -ti "tcp:${port}" -sTCP:LISTEN 2>/dev/null)
    else
        mapfile -t remaining < <(fuser -n tcp "${port}" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+$')
    fi

    if (( ${#remaining[@]} == 0 )); then
        return 0
    fi

    # Segundo intento con KILL si signal != KILL
    if [[ "$signal" != "KILL" && "$signal" != "9" ]]; then
        for pid in "${remaining[@]}"; do
            [[ -z "$pid" ]] && continue
            kill -KILL "$pid" 2>/dev/null && echo "KILLED pid=${pid} signal=KILL port=${port}"
        done
        sleep 1
        local still=()
        if [[ "$tool" == "lsof" ]]; then
            mapfile -t still < <(lsof -ti "tcp:${port}" -sTCP:LISTEN 2>/dev/null)
        else
            mapfile -t still < <(fuser -n tcp "${port}" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+$')
        fi
        if (( ${#still[@]} > 0 )); then
            echo "ERROR: puerto ${port} sigue ocupado tras SIGKILL" >&2
            return 3
        fi
    else
        echo "ERROR: puerto ${port} sigue ocupado tras SIGKILL" >&2
        return 3
    fi

    return 0
}
