#!/bin/bash
# lastact: [nacho@2026-06-08]
# desc: Script gráfico para crear y gestionar un Punto de Acceso WiFi (AP) usando nmcli

FICHFUNCS="/usr/bin/vx-funcs-bash"
[ -f "${FICHFUNCS}" ] && . "${FICHFUNCS}" "null"

# ---------------------------------------------------------------------------
# 0) Constantes y valores por defecto
# ---------------------------------------------------------------------------
TITULO="Gestionar Punto de Acceso WiFi (AP)"
ICONO_YAD="vx-ap-wifi"
IMAGEN_YAD="network-wireless"
SSID_DEFAULT="VXROBOTAP"
PASS_DEFAULT="12345678"
AP_CON_NAME_PREFIX="vx-ap-wifi"

# ---------------------------------------------------------------------------
# 1) Verificación de permisos root
# ---------------------------------------------------------------------------
if [ "$(id -u)" -ne 0 ]; then
    yad --title "${TITULO}" \
        --text "Necesitas privilegios de <b>root</b> para gestionar puntos de acceso WiFi." \
        --window-icon "${ICONO_YAD}" \
        --image "${IMAGEN_YAD}" \
        --width="420" --height="120" \
        --center \
        --text-align="center" \
        --buttons-layout center \
        --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 2) Detectar interfaces de red disponibles
# ---------------------------------------------------------------------------

# Interfaces WiFi disponibles (modo managed o no ocupadas en AP ya activo)
mapfile -t WIFI_IFACES < <(nmcli -t -f DEVICE,TYPE dev | grep ":wifi$" | cut -d: -f1)

# Interfaces que pueden hacer de puente/WAN (ethernet o wifi no usada como AP)
mapfile -t BRIDGE_IFACES < <(nmcli -t -f DEVICE,TYPE,STATE dev | \
    grep -E ":ethernet:|:wifi:" | \
    grep -v ":unmanaged" | \
    cut -d: -f1)

# ---------------------------------------------------------------------------
# 3) Verificar que hay al menos una interfaz WiFi disponible
# ---------------------------------------------------------------------------
if [ "${#WIFI_IFACES[@]}" -eq 0 ]; then
    yad --title "${TITULO}" \
        --text "❌ No se ha detectado ninguna tarjeta inalámbrica en el sistema.\n\nNo es posible crear un Punto de Acceso WiFi." \
        --window-icon "${ICONO_YAD}" \
        --image "${IMAGEN_YAD}" \
        --width="480" --height="150" \
        --center \
        --text-align="center" \
        --buttons-layout center \
        --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 4) Verificar que hay al menos una interfaz que pueda hacer de puente (distinta a la AP)
# ---------------------------------------------------------------------------
# Necesitamos al menos 2 interfaces de red en total para poder funcionar como AP+WAN
TOTAL_IFACES="${#BRIDGE_IFACES[@]}"
if [ "${TOTAL_IFACES}" -lt 2 ]; then
    yad --title "${TITULO}" \
        --text "❌ Se necesita al menos <b>2 interfaces de red</b> para crear un AP:\n• Una tarjeta WiFi para emitir el punto de acceso\n• Otra interfaz (ethernet o WiFi) con acceso a Internet\n\nSolo se ha detectado ${TOTAL_IFACES} interfaz/ces de red." \
        --window-icon "${ICONO_YAD}" \
        --image "${IMAGEN_YAD}" \
        --width="520" --height="180" \
        --center \
        --text-align="center" \
        --buttons-layout center \
        --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 5) Detectar conexiones AP ya existentes en NetworkManager
# ---------------------------------------------------------------------------
mapfile -t AP_EXISTENTES < <(nmcli -t -f NAME,TYPE con show | grep ":.*wireless" | cut -d: -f1)
# Filtrar las que son realmente de tipo AP (modo ap)
AP_CON_LIST=()
for CON in "${AP_EXISTENTES[@]}"; do
    MODE=$(nmcli -t -f 802-11-wireless.mode con show "${CON}" 2>/dev/null | cut -d: -f2 | tr -d ' ')
    [ "${MODE}" = "ap" ] && AP_CON_LIST+=("${CON}")
done

# ---------------------------------------------------------------------------
# 6) Construir listas para yad
# ---------------------------------------------------------------------------

# Lista de interfaces WiFi para el selector (columna combo)
WIFI_COMBO=$(printf "%s\n" "${WIFI_IFACES[@]}" | tr '\n' '!' | sed 's/!$//')

# Lista de interfaces para WAN/puente
BRIDGE_COMBO=$(printf "%s\n" "${BRIDGE_IFACES[@]}" | tr '\n' '!' | sed 's/!$//')

# ---------------------------------------------------------------------------
# 7) Menú principal: listar AP existentes y ofrecer crear uno nuevo (fusionado)
# ---------------------------------------------------------------------------
# Si no hay conexiones AP existentes, saltamos directamente a crear nuevo.
if [ "${#AP_CON_LIST[@]}" -eq 0 ]; then
    # No hay APs existentes: seguiremos al flujo de creación
    SELEC_CREAR_NUEVO="TRUE"
else
    # Construir lista radio para yad con opción adicional para crear uno nuevo
    RADIO_ARGS=()
    # Añadir opción para crear nuevo AP (por defecto seleccionada)
    RADIO_ARGS+=("TRUE" "Crear nuevo AP")
    for CON_AP in "${AP_CON_LIST[@]}"; do
        SSID_AP=$(nmcli -t -f 802-11-wireless.ssid con show "${CON_AP}" 2>/dev/null | cut -d: -f2 | tr -d ' ')
        DESC="${CON_AP} (SSID: ${SSID_AP:-desconocido})"
        RADIO_ARGS+=("FALSE" "${DESC}")
    done

    SEL=$(yad --title "${TITULO}" \
        --list --radiolist \
        --window-icon "${ICONO_YAD}" \
        --image "${IMAGEN_YAD}" \
        --center \
        --width="620" --height="340" \
        --text "<b>Selecciona un AP para activar o elige crear uno nuevo:</b>" \
        --text-align="center" \
        --column "Sel:RD" --column "Conexión / Acción:TEXT" \
        "${RADIO_ARGS[@]}" \
        --buttons-layout center \
        --button="<b>Seleccionar</b>":0 \
        --button="Cancelar":1)
    RET=$?
    [ "${RET}" -ne 0 ] && exit 0

    SELEC_CREAR_NUEVO=""
    SELEC=$(echo "${SEL}" | cut -d'|' -f2)
    SELEC=$(echo "${SELEC}" | xargs)
    if [ "${SELEC}" = "Crear nuevo AP" ]; then
        SELEC_CREAR_NUEVO="TRUE"
    else
        # Extraer nombre de la conexión seleccionada (quitando la parte SSID)
        CON_SELECCIONADA=$(echo "${SELEC}" | sed 's/ (SSID:.*//')
        CON_SELECCIONADA=$(echo "${CON_SELECCIONADA}" | xargs)
    fi
fi

# Si se seleccionó una conexión existente, activarla y salir.
if [ "${SELEC_CREAR_NUEVO}" != "TRUE" ] && [ -n "${CON_SELECCIONADA}" ]; then
    OUTPUT=$(nmcli con up "${CON_SELECCIONADA}" 2>&1)
    RET_NM=$?
    if [ "${RET_NM}" -eq 0 ]; then
        yad --title "${TITULO}" \
            --text "✅ <b>Punto de Acceso activado correctamente</b>\n\nConexión: <b>${CON_SELECCIONADA}</b>\n\n${OUTPUT}" \
            --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
            --width="480" --height="180" --center --text-align="center" \
            --buttons-layout center --button="Cerrar":0
    else
        yad --title "${TITULO}" \
            --text "❌ <b>Error al activar el punto de acceso</b>\n\nConexión: <b>${CON_SELECCIONADA}</b>\n\n${OUTPUT}" \
            --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
            --width="520" --height="220" --center --text-align="center" \
            --buttons-layout center --button="Cerrar":1
    fi
    exit 0
fi

# ---------------------------------------------------------------------------
# 9) Rama: CREAR NUEVO AP
# ---------------------------------------------------------------------------

# Selección de interfaz WiFi para el AP (si hay más de una)
WIFI_AP_IFACE="${WIFI_IFACES[0]}"
if [ "${#WIFI_IFACES[@]}" -gt 1 ]; then
    SEL_WIFI=$(yad --title "${TITULO}" \
        --form \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --center --width="460" --height="160" \
        --text "<b>Interfaz WiFi para emitir el AP:</b>" \
        --text-align="center" \
        --field="Interfaz WiFi (AP):CB" "${WIFI_COMBO}" \
        --buttons-layout center \
        --button="<b>Siguiente</b>":0 \
        --button="Cancelar":1)
    RET=$?
    [ "${RET}" -ne 0 ] && exit 0
    WIFI_AP_IFACE=$(echo "${SEL_WIFI}" | cut -d'|' -f1 | xargs)
fi

# Selección de interfaz de puente/WAN (diferente a la AP)
# Filtramos la interfaz AP de las opciones de puente
BRIDGE_IFACES_FILTRADAS=()
for IFACE in "${BRIDGE_IFACES[@]}"; do
    [ "${IFACE}" != "${WIFI_AP_IFACE}" ] && BRIDGE_IFACES_FILTRADAS+=("${IFACE}")
done

if [ "${#BRIDGE_IFACES_FILTRADAS[@]}" -eq 0 ]; then
    yad --title "${TITULO}" \
        --text "❌ No queda ninguna interfaz disponible para actuar como enlace a Internet (diferente a <b>${WIFI_AP_IFACE}</b>).\n\nConecta un cable Ethernet o añade otra tarjeta de red." \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="520" --height="160" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 10) Formulario de configuración del AP
# ---------------------------------------------------------------------------
BRIDGE_COMBO_FILT=$(printf "%s\n" "${BRIDGE_IFACES_FILTRADAS[@]}" | tr '\n' '!' | sed 's/!$//')

FORM=$(yad --title "${TITULO}" \
    --form \
    --window-icon "${ICONO_YAD}" \
    --image "${IMAGEN_YAD}" \
    --center \
    --width="520" --height="320" \
    --text "<b>Configuración del nuevo Punto de Acceso WiFi</b>\n\nRellena o modifica los parámetros del AP:" \
    --text-align="center" \
    --field="Nombre de la conexión:" "${AP_CON_NAME_PREFIX}" \
    --field="SSID (nombre red WiFi):" "${SSID_DEFAULT}" \
    --field="Contraseña WiFi:" "${PASS_DEFAULT}" \
    --field="Interfaz AP (WiFi):" "${WIFI_AP_IFACE}" \
    --field="Interfaz WAN/puente:CB" "${BRIDGE_COMBO_FILT}" \
    --field="Ocultar red (Hidden):CHK" "FALSE" \
    --buttons-layout center \
    --button="<b>Crear y Activar AP</b>":0 \
    --button="Cancelar":1)

RET=$?
[ "${RET}" -ne 0 ] && exit 0

# Parsear resultados del formulario
CON_NAME=$(echo "${FORM}" | cut -d'|' -f1 | xargs)
AP_SSID=$(echo "${FORM}" | cut -d'|' -f2 | xargs)
AP_PASS=$(echo "${FORM}" | cut -d'|' -f3 | xargs)
AP_IFACE=$(echo "${FORM}" | cut -d'|' -f4 | xargs)
WAN_IFACE=$(echo "${FORM}" | cut -d'|' -f5 | xargs)
HIDDEN_RAW=$(echo "${FORM}" | cut -d'|' -f6 | xargs)
[ "${HIDDEN_RAW}" = "TRUE" ] && AP_HIDDEN="yes" || AP_HIDDEN="no"

# ---------------------------------------------------------------------------
# 11) Validaciones básicas
# ---------------------------------------------------------------------------
if [ -z "${CON_NAME}" ] || [ -z "${AP_SSID}" ] || [ -z "${AP_PASS}" ]; then
    yad --title "${TITULO}" \
        --text "⚠️ El nombre de conexión, SSID y contraseña son obligatorios." \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="400" --height="130" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":1
    exit 1
fi

if [ "${#AP_PASS}" -lt 8 ]; then
    yad --title "${TITULO}" \
        --text "⚠️ La contraseña WiFi debe tener al menos <b>8 caracteres</b>." \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="420" --height="130" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 12) Comprobar si ya existe una conexión con ese nombre y preguntar
# ---------------------------------------------------------------------------
if nmcli con show "${CON_NAME}" &>/dev/null; then
    yad --title "${TITULO}" \
        --text "⚠️ Ya existe una conexión llamada <b>${CON_NAME}</b>.\n\n¿Deseas <b>eliminarla y recrearla</b> con la nueva configuración?" \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="480" --height="160" --center --text-align="center" \
        --buttons-layout center \
        --button="Sí, eliminar y recrear":0 \
        --button="Cancelar":1
    RET=$?
    [ "${RET}" -ne 0 ] && exit 0
    nmcli con delete "${CON_NAME}" &>/dev/null
fi

# ---------------------------------------------------------------------------
# 13) Crear la conexión AP con nmcli
# ---------------------------------------------------------------------------
OUTPUT=$(nmcli con add \
    type wifi \
    ifname "${AP_IFACE}" \
    con-name "${CON_NAME}" \
    autoconnect no \
    ssid "${AP_SSID}" \
    mode ap \
    802-11-wireless.hidden "${AP_HIDDEN}" \
    ipv4.method shared \
    wifi-sec.key-mgmt wpa-psk \
    wifi-sec.psk "${AP_PASS}" \
    2>&1)
RET_NM=$?

if [ "${RET_NM}" -ne 0 ]; then
    yad --title "${TITULO}" \
        --text "❌ <b>Error al crear la conexión AP</b>\n\nDetalle:\n${OUTPUT}" \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="560" --height="250" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":1
    exit 1
fi

# ---------------------------------------------------------------------------
# 14) Activar la conexión AP recién creada
# ---------------------------------------------------------------------------
OUTPUT_UP=$(nmcli con up "${CON_NAME}" 2>&1)
RET_UP=$?

if [ "${RET_UP}" -eq 0 ]; then
    # Obtener la IP que el AP usará como gateway (asignada por shared/NAT)
    sleep 1
    AP_IP=$(ip -4 addr show "${AP_IFACE}" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
    yad --title "${TITULO}" \
        --text "✅ <b>Punto de Acceso creado y activado correctamente</b>\n\n\
🔷 Conexión:   <b>${CON_NAME}</b>\n\
📶 SSID:       <b>${AP_SSID}</b>\n\
🔑 Contraseña: <b>${AP_PASS}</b>\n\
📡 Interfaz AP: <b>${AP_IFACE}</b>\n\
🌐 Interfaz WAN: <b>${WAN_IFACE}</b>\n\
🔒 Oculta:     <b>${AP_HIDDEN}</b>\n\
🏠 IP Gateway: <b>${AP_IP:-desconocida (asignada dinámicamente)}</b>" \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="520" --height="280" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":0
else
    yad --title "${TITULO}" \
        --text "⚠️ La conexión AP <b>${CON_NAME}</b> se ha creado pero <b>no se ha podido activar</b>.\n\nDetalle:\n${OUTPUT_UP}\n\nPuedes intentar activarla más tarde con:\n<tt>nmcli con up \"${CON_NAME}\"</tt>" \
        --window-icon "${ICONO_YAD}" --image "${IMAGEN_YAD}" \
        --width="560" --height="280" --center --text-align="center" \
        --buttons-layout center --button="Cerrar":1
fi

exit 0
