#!/bin/bash
# =============================================================================
# kiosk-manager.sh — Debian 13 (Trixie)
# Arquitectura: lightdm autologin → openbox → chromium --kiosk
# lightdm gestiona sesión logind y seat correctamente (sin entorno gráfico)
# Requiere: root
# =============================================================================

SELECTED_USER=""
BROWSER_BIN=""

# ─── utilidades ───────────────────────────────────────────────────────────────

check_root() {
    [[ "$EUID" -ne 0 ]] && { echo "❌ Ejecutar como root"; exit 1; }
}

detect_browser() {
    BROWSER_BIN=$(command -v firefox-esr 2>/dev/null                || command -v firefox 2>/dev/null                || true)
}

pause() {
    echo ""
    read -rp "  Pulsa ENTER para continuar..."
}

user_home() {
    getent passwd "$1" | cut -d: -f6
}

# ─── 1. Crear usuario ─────────────────────────────────────────────────────────

create_user() {
    echo ""
    echo "  ╔─ PASO 1: Crear usuario kiosk ──────────────────────╗"
    echo ""
    read -rp "  Nombre de usuario: " NEW_USER
    echo ""

    if [ -z "$NEW_USER" ]; then
        echo "  ❌ Nombre vacío"
        pause; return 1
    fi

    if id "$NEW_USER" &>/dev/null; then
        echo "  ⚠ El usuario '$NEW_USER' ya existe"
        read -rp "  ¿Usar este usuario? [s/N]: " yn
        [[ "$yn" != "s" && "$yn" != "S" ]] && { pause; return 1; }
        SELECTED_USER="$NEW_USER"
        echo "  ✔ Usando: $SELECTED_USER"
    else
        adduser \
            --disabled-password \
            --gecos "Kiosk" \
            --shell /bin/bash \
            "$NEW_USER"

        passwd -l "$NEW_USER"
        SELECTED_USER="$NEW_USER"
        echo ""
        echo "  ✔ Usuario creado: $SELECTED_USER"
    fi

    echo ""
    echo "  Aplicando privilegios mínimos..."
    # video y render se mantienen: necesarios para acceso GPU
    for grp in sudo adm dialout cdrom floppy plugdev netdev; do
        deluser "$SELECTED_USER" "$grp" 2>/dev/null || true
    done
    usermod -aG video  "$SELECTED_USER"
    usermod -aG render "$SELECTED_USER" 2>/dev/null || true

    echo "  ✔ Grupos configurados (video y render incluidos para GPU)"
    echo ""
    echo "  ╚────────────────────────────────────────────────────╝"
    pause
}

# ─── 2. Instalar paquetes ─────────────────────────────────────────────────────

install_packages() {
    echo ""
    echo "  ╔─ PASO 2: Instalar paquetes ────────────────────────╗"
    echo ""

    echo "  Actualizando índice..."
    apt-get update -qq

    echo "  Instalando stack X + lightdm + openbox + firefox-esr..."
    # lightdm:             display manager — gestiona sesión logind y seat
    # lightdm-gtk-greeter: greeter requerido por lightdm (no visible con autologin)
    # openbox:             WM mínimo sin compositor ni escritorio
    # chromium:            navegador kiosk
    # x11-xserver-utils:   xset (screensaver/DPMS)
    # x11-utils:           xrandr
    # unclutter-xfixes:    ocultar cursor
    # fonts-liberation:    fuentes base para chromium
    apt-get install -y --no-install-recommends \
        lightdm \
        lightdm-gtk-greeter \
        openbox \

        x11-xserver-utils \
        x11-utils \
        unclutter-xfixes \
        fonts-liberation

    detect_browser
    if [ -z "$BROWSER_BIN" ]; then
        echo "  ❌ Firefox ESR no encontrado tras la instalación"
        pause; return 1
    fi

    echo ""
    echo "  ✔ Firefox ESR: $BROWSER_BIN"
    echo "  ✔ lightdm instalado"
    echo "  ✔ openbox instalado"
    echo ""
    echo "  ╚────────────────────────────────────────────────────╝"
    pause
}

# ─── 3. Configurar kiosk ──────────────────────────────────────────────────────

setup_kiosk() {
    echo ""
    echo "  ╔─ PASO 3: Configurar kiosk ─────────────────────────╗"
    echo ""

    if [ -z "$SELECTED_USER" ]; then
        echo "  ❌ Ejecuta primero el Paso 1"
        pause; return 1
    fi
    if ! id "$SELECTED_USER" &>/dev/null; then
        echo "  ❌ Usuario '$SELECTED_USER' no existe"
        pause; return 1
    fi

    detect_browser
    if [ -z "$BROWSER_BIN" ]; then
        echo "  ❌ Firefox ESR no instalado — ejecuta primero el Paso 2"
        pause; return 1
    fi

    local url
    while true; do
        read -rp "  URL del kiosk: " url
        [[ "$url" =~ ^https?:// ]] && break
        echo "  ❌ Debe empezar por http:// o https://"
    done

    local home_dir
    home_dir=$(user_home "$SELECTED_USER")
    echo ""

    # ── [1/6] Limpiar configuración anterior si existe ────────────────────────
    echo "  [1/6] Limpiando configuración anterior..."
    rm -f  "$home_dir/.bash_profile"
    rm -rf "/etc/systemd/system/getty@tty7.service.d"
    systemctl daemon-reload 2>/dev/null || true
    echo "  ✔ Limpieza completada"

    # ── [2/6] Openbox: rc.xml sin keybindings ni menú ────────────────────────
    echo "  [2/6] Configurando Openbox..."
    local ob_dir="$home_dir/.config/openbox"
    mkdir -p "$ob_dir"

    # rc.xml: sin atajos de teclado, sin menú contextual, Chromium fullscreen
    cat > "$ob_dir/rc.xml" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<openbox_config xmlns="http://openbox.org/3.4/rc"
                xmlns:xi="http://www.w3.org/2001/XInclude">
  <focus>
    <focusNew>yes</focusNew>
    <followMouse>no</followMouse>
  </focus>
  <desktops>
    <number>1</number>
    <firstdesk>1</firstdesk>
    <popupTime>0</popupTime>
  </desktops>
  <margins>
    <top>0</top><bottom>0</bottom><left>0</left><right>0</right>
  </margins>
  <!-- Sin atajos de teclado: Alt+F4, Alt+Tab, Ctrl+Alt+T desactivados -->
  <keyboard>
    <chainQuitKey>C-g</chainQuitKey>
  </keyboard>
  <!-- Sin menú contextual en el escritorio -->
  <mouse>
    <dragThreshold>1</dragThreshold>
    <doubleClickTime>200</doubleClickTime>
    <screenEdgeWarpTime>0</screenEdgeWarpTime>
    <screenEdgeWarpMouse>false</screenEdgeWarpMouse>
  </mouse>
  <menu>
    <hideDelay>200</hideDelay>
    <middle>no</middle>
    <manageDesktops>no</manageDesktops>
  </menu>
  <!-- Firefox ESR: fullscreen, sin decoraciones de ventana -->
  <applications>
    <application name="Navigator" class="firefox-esr">
      <decor>no</decor>
      <maximized>true</maximized>
      <fullscreen>true</fullscreen>
      <focus>yes</focus>
      <layer>above</layer>
      <desktop>1</desktop>
    </application>
    <application name="Navigator" class="Firefox-esr">
      <decor>no</decor>
      <maximized>true</maximized>
      <fullscreen>true</fullscreen>
      <focus>yes</focus>
      <layer>above</layer>
      <desktop>1</desktop>
    </application>
  </applications>
</openbox_config>
EOF

    cat > "$ob_dir/menu.xml" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<openbox_menu xmlns="http://openbox.org/3.4/menu">
</openbox_menu>
EOF

    # autostart: lanza Chromium al arrancar openbox
    cat > "$ob_dir/autostart" <<EOF
# Desactivar screensaver y DPMS
xset s off
xset s noblank
xset -dpms

# Ocultar cursor tras 3s de inactividad
command -v unclutter &>/dev/null && unclutter --timeout 3 --fork

# Esperar a que openbox inicialice completamente
sleep 1

# Chromium en modo kiosk
$BROWSER_BIN \\
    --kiosk "$url" \\
\
    --no-first-run \\
    --no-sandbox \\
    --disable-infobars \\
    --disable-session-crashed-bubble \\
    --disable-translate \\
    --disable-extensions \\
    --disable-sync \\
    --disable-background-networking \\
    --disable-features=TranslateUI \\
    --check-for-update-interval=31536000 \\
    --noerrdialogs &
EOF

    chown -R "$SELECTED_USER":"$SELECTED_USER" "$ob_dir"
    echo "  ✔ Openbox configurado (sin keybindings, sin menú)"

    # ── [3/6] Guardar URL ─────────────────────────────────────────────────────
    echo "$url" > "$home_dir/.kiosk_url"
    chown "$SELECTED_USER":"$SELECTED_USER" "$home_dir/.kiosk_url"

    # ── [4/6] lightdm: autologin directo al usuario kiosk ────────────────────
    # lightdm gestiona correctamente:
    #   - sesión logind (seat0 asignado)
    #   - acceso a dispositivos DRM/GPU via logind
    #   - D-Bus de sesión
    # Con autologin-user-timeout=0 el greeter no se muestra nunca
    echo "  [4/6] Configurando lightdm autologin..."
    mkdir -p /etc/lightdm/lightdm.conf.d

    cat > /etc/lightdm/lightdm.conf.d/kiosk.conf <<EOF
[Seat:*]
autologin-guest=false
autologin-user=$SELECTED_USER
autologin-user-timeout=0
autologin-session=openbox
greeter-session=lightdm-gtk-greeter
EOF

    echo "  ✔ /etc/lightdm/lightdm.conf.d/kiosk.conf"

    # ── [5/6] Activar lightdm y target correcto ───────────────────────────────
    echo "  [5/6] Activando lightdm..."
    systemctl set-default graphical.target
    systemctl enable lightdm
    echo "  ✔ lightdm habilitado — target: graphical.target"

    # ── [6/6] OverlayFS: reset completo del home en cada reinicio ─────────────
    # Arquitectura:
    #   lowerdir = /opt/kiosk-base/USER  (copia limpia, solo lectura)
    #   upperdir = tmpfs en /run         (cambios de sesión, se pierde al reiniciar)
    #   merged   = /home/USER            (lo que ve el usuario)
    # En cada reinicio upperdir es tmpfs vacío → home vuelve al estado original
    echo "  [6/6] Configurando OverlayFS (reset en cada reinicio)..."

    local base_dir="/opt/kiosk-base/$SELECTED_USER"

    # Parar sesión activa si existe para poder copiar el home limpio
    pkill -u "$SELECTED_USER" 2>/dev/null || true
    sleep 1

    # Desmontar overlay previo si existe
    umount "/home/$SELECTED_USER" 2>/dev/null || true

    # Crear copia base del home ya configurado
    rm -rf "$base_dir"
    mkdir -p "$base_dir"
    cp -a "$home_dir/." "$base_dir/"
    echo "  ✔ Base guardada en: $base_dir"

    # Servicio systemd que monta el overlay ANTES de que lightdm arranque
    cat > "/etc/systemd/system/kiosk-overlay-${SELECTED_USER}.service" <<EOF
[Unit]
Description=Kiosk overlay reset para $SELECTED_USER
Before=lightdm.service
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
# Crear directorios upper y work en /run (ya es tmpfs, se limpia en cada arranque)
ExecStartPre=/bin/mkdir -p /run/kiosk-${SELECTED_USER}-upper /run/kiosk-${SELECTED_USER}-work
# Montar overlay: cualquier escritura va a upper (tmpfs), lowerdir es intocable
ExecStart=/bin/mount -t overlay overlay \
    -o lowerdir=$base_dir,upperdir=/run/kiosk-${SELECTED_USER}-upper,workdir=/run/kiosk-${SELECTED_USER}-work \
    /home/$SELECTED_USER
# Al parar: desmontar limpiamente
ExecStop=/bin/umount -l /home/$SELECTED_USER

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable "kiosk-overlay-${SELECTED_USER}.service"
    echo "  ✔ Overlay habilitado — activo desde el próximo arranque"

    echo ""
    echo "  ╚────────────────────────────────────────────────────╝"
    echo ""
    echo "  ╔─ Configuración completada ─────────────────────────╗"
    printf "  ║  Usuario   : %-37s║\n" "$SELECTED_USER"
    printf "  ║  URL       : %-37s║\n" "${url:0:37}"
    echo "  ║  Sesión    : lightdm → openbox → firefox-esr      ║"
    echo "  ║  Overlay   : reset completo en cada reinicio       ║"
    echo "  ║  Base      : /opt/kiosk-base/$SELECTED_USER         ║"
    echo "  ║                                                    ║"
    echo "  ║  ⚠ Reinicia el equipo para activar el overlay:     ║"
    echo "  ║    reboot                                          ║"
    echo "  ╚════════════════════════════════════════════════════╝"
    pause
}

# ─── estado ───────────────────────────────────────────────────────────────────

status() {
    echo ""
    echo "  ── Sistema ──────────────────────────────────────────"
    printf "  Target   : %s\n" "$(systemctl get-default 2>/dev/null)"
    printf "  lightdm  : %s\n" "$(systemctl is-active lightdm 2>/dev/null)"

    echo ""
    echo "  ── Autologin configurado ────────────────────────────"
    local conf="/etc/lightdm/lightdm.conf.d/kiosk.conf"
    if [ -f "$conf" ]; then
        grep -E "autologin-user=|autologin-session=" "$conf"
    else
        echo "  ⚠ Sin configuración de autologin"
    fi

    echo ""
    echo "  ── OverlayFS ────────────────────────────────────────"
    if mount | grep -q 'overlay on /home'; then
        mount | grep 'overlay on /home' | awk '{printf "  ✔ Activo: %s\n", $3}'
    else
        echo "  ⚠ Overlay no montado (reinicia para activarlo)"
    fi

    echo ""
    echo "  ── lightdm ──────────────────────────────────────────"
    systemctl status lightdm --no-pager --lines=5

    echo ""
    echo "  ── Procesos kiosk activos ───────────────────────────"
    ps aux | grep -E "Xorg|openbox|firefox|lightdm" | grep -v grep \
        | awk '{printf "  %-12s %s\n", $1, $11}' \
        || echo "  (ninguno)"

    pause
}

# ─── desinstalar ──────────────────────────────────────────────────────────────

uninstall_kiosk() {
    echo ""
    echo "  Usuarios disponibles (UID ≥ 1000):"
    echo "  ------------------------------------"
    getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 { print "  " $1 }' | sort
    echo "  ------------------------------------"
    read -rp "  Usuario a desinstalar: " DEL_USER

    if ! id "$DEL_USER" &>/dev/null; then
        echo "  ❌ Usuario '$DEL_USER' no existe"
        pause; return 1
    fi

    local home_dir
    home_dir=$(user_home "$DEL_USER")

    echo ""
    echo "  ⚠ Se eliminará la configuración kiosk de: $DEL_USER"
    echo "  El usuario y su home NO se borran"
    read -rp "  ¿Confirmar? [s/N]: " confirm
    [[ "$confirm" != "s" && "$confirm" != "S" ]] && { echo "  Cancelado"; pause; return; }

    echo ""

    # Matar sesión activa
    pkill -u "$DEL_USER" 2>/dev/null && echo "  ✔ Sesión terminada" || true

    # Desmontar y eliminar overlay
    umount "/home/$DEL_USER" 2>/dev/null || true
    systemctl stop    "kiosk-overlay-${DEL_USER}.service" 2>/dev/null || true
    systemctl disable "kiosk-overlay-${DEL_USER}.service" 2>/dev/null || true
    rm -f "/etc/systemd/system/kiosk-overlay-${DEL_USER}.service"
    rm -rf "/opt/kiosk-base/$DEL_USER"
    rm -rf "/run/kiosk-${DEL_USER}-upper" "/run/kiosk-${DEL_USER}-work"
    echo "  ✔ Overlay eliminado"

    # Eliminar configuración lightdm
    rm -f /etc/lightdm/lightdm.conf.d/kiosk.conf
    echo "  ✔ Configuración lightdm eliminada"

    # Deshabilitar lightdm
    systemctl disable lightdm 2>/dev/null || true
    systemctl set-default multi-user.target
    echo "  ✔ lightdm deshabilitado"

    # Eliminar configuración X del usuario
    rm -f  "$home_dir/.kiosk_url"
    rm -f  "$home_dir/.config/openbox/rc.xml"
    rm -f  "$home_dir/.config/openbox/menu.xml"
    rm -f  "$home_dir/.config/openbox/autostart"
    echo "  ✔ Configuración openbox eliminada"

    [ "$SELECTED_USER" = "$DEL_USER" ] && SELECTED_USER=""
    echo ""
    echo "  ✔ Desinstalado correctamente"
    pause
}

# ─── menú ─────────────────────────────────────────────────────────────────────

menu() {
    clear
    detect_browser
    local lightdm_status
    lightdm_status=$(systemctl is-active lightdm 2>/dev/null || echo "inactivo")

    echo ""
    echo "  ╔══════════════════════════════════════════════╗"
    echo "  ║     KIOSK MANAGER — Debian 13 (Trixie)       ║"
    echo "  ╠══════════════════════════════════════════════╣"
    printf "  ║  Usuario  : %-33s║\n" "${SELECTED_USER:-<ninguno>}"
    printf "  ║  Browser  : %-33s║\n" "${BROWSER_BIN:-<no instalado>}"
    printf "  ║  lightdm  : %-33s║\n" "$lightdm_status"
    echo "  ╠══════════════════════════════════════════════╣"
    echo "  ║                                              ║"
    echo "  ║  1) Crear usuario kiosk                      ║"
    echo "  ║  2) Instalar paquetes                        ║"
    echo "  ║  3) Configurar kiosk                         ║"
    echo "  ║  ─────────────────────────────               ║"
    echo "  ║  4) Estado                                   ║"
    echo "  ║  5) Desinstalar kiosk                        ║"
    echo "  ║  6) Salir                                    ║"
    echo "  ║                                              ║"
    echo "  ╚══════════════════════════════════════════════╝"
    echo ""
    read -rp "  Opción: " opt
    echo ""

    case "$opt" in
        1) create_user ;;
        2) install_packages ;;
        3) setup_kiosk ;;
        4) status ;;
        5) uninstall_kiosk ;;
        6) echo "  Saliendo..."; exit 0 ;;
        *) echo "  ⚠ Opción no válida"; sleep 1 ;;
    esac
}

# ─── entrada ──────────────────────────────────────────────────────────────────

check_root
while true; do menu; done
