#!/bin/bash
# ══════════════════════════════════════════════════════════════════
#  secubox-kiosk-launcher — X11 Kiosk via nodm
#  Uses nodm display manager for reliable X11 startup
#  Compatible with VirtualBox, VMware, QEMU, bare metal
# ══════════════════════════════════════════════════════════════════
# NOTE: Not using pipefail - we need graceful degradation on real HW
set -u

readonly KIOSK_USER="secubox-kiosk"
readonly KIOSK_HOME="/home/secubox-kiosk"
readonly LOG_TAG="secubox-kiosk"
readonly FAIL_COUNT_FILE="/tmp/.kiosk-fail-count"
readonly MAX_FAILURES=3

log() { echo "[kiosk] $*" >&2; logger -t "$LOG_TAG" "$*" 2>/dev/null || true; }
err() { echo "[kiosk] ERROR: $*" >&2; logger -t "$LOG_TAG" -p err "$*" 2>/dev/null || true; }

# Track failures to prevent infinite restart loop
track_failure() {
    local count=0
    [[ -f "$FAIL_COUNT_FILE" ]] && count=$(cat "$FAIL_COUNT_FILE" 2>/dev/null || echo 0)
    count=$((count + 1))
    echo "$count" > "$FAIL_COUNT_FILE"

    if [[ $count -ge $MAX_FAILURES ]]; then
        err "Too many failures ($count). Disabling kiosk to prevent boot loop."
        rm -f /var/lib/secubox/.kiosk-enabled
        # Show message on console
        echo ""
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  KIOSK DISABLED - Too many X11 failures                   ║"
        echo "║  Check: journalctl -u secubox-kiosk                       ║"
        echo "║  Re-enable: touch /var/lib/secubox/.kiosk-enabled         ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        exit 1
    fi
    log "Failure $count of $MAX_FAILURES"
}

clear_failures() {
    rm -f "$FAIL_COUNT_FILE"
}

# ══════════════════════════════════════════════════════════════════
# DEBUG: Generate diagnostic report for VirtualBox/VM troubleshooting
# ══════════════════════════════════════════════════════════════════
readonly DEBUG_REPORT="/tmp/kiosk-debug-$(date +%Y%m%d-%H%M%S).log"

generate_debug_report() {
    local report="$DEBUG_REPORT"
    {
        echo "═══════════════════════════════════════════════════════════════"
        echo "SecuBox Kiosk Debug Report - $(date -Iseconds)"
        echo "═══════════════════════════════════════════════════════════════"
        echo ""

        echo "▶ SYSTEM INFO:"
        echo "  Hostname: $(hostname)"
        echo "  Kernel: $(uname -r)"
        echo "  Architecture: $(uname -m)"
        echo ""

        echo "▶ VIRTUALIZATION:"
        echo "  systemd-detect-virt: $(systemd-detect-virt 2>/dev/null || echo 'N/A')"
        echo "  DMI Product: $(cat /sys/class/dmi/id/product_name 2>/dev/null || echo 'N/A')"
        echo "  DMI Vendor: $(cat /sys/class/dmi/id/sys_vendor 2>/dev/null || echo 'N/A')"
        echo ""

        echo "▶ GRAPHICS HARDWARE:"
        lspci 2>/dev/null | grep -iE "vga|display|graphics|3d" || echo "  No PCI graphics found"
        echo ""

        echo "▶ DRM/KMS DEVICES:"
        ls -la /dev/dri/ 2>/dev/null || echo "  No DRM devices"
        echo ""

        echo "▶ FRAMEBUFFER:"
        ls -la /dev/fb* 2>/dev/null || echo "  No framebuffer devices"
        cat /sys/class/graphics/fb0/virtual_size 2>/dev/null && echo "(fb0 virtual size)"
        echo ""

        echo "▶ TTY STATUS:"
        fgconsole 2>/dev/null && echo "(current VT)"
        cat /sys/class/tty/tty0/active 2>/dev/null && echo "(active tty)"
        who 2>/dev/null | head -5
        echo ""

        echo "▶ KIOSK FLAG FILES:"
        ls -la /var/lib/secubox/.kiosk* 2>/dev/null || echo "  No kiosk flags found"
        echo ""

        echo "▶ KIOSK USER:"
        id "$KIOSK_USER" 2>/dev/null || echo "  User not found: $KIOSK_USER"
        ls -la "$KIOSK_HOME"/.x* 2>/dev/null || echo "  No xsession files"
        echo ""

        echo "▶ X11 CONFIG:"
        ls -la /etc/X11/xorg.conf.d/ 2>/dev/null || echo "  No xorg.conf.d"
        cat /etc/X11/xorg.conf.d/*.conf 2>/dev/null || true
        cat /etc/X11/Xwrapper.config 2>/dev/null || echo "  No Xwrapper.config"
        echo ""

        echo "▶ LOADED KERNEL MODULES (video-related):"
        lsmod 2>/dev/null | grep -iE "drm|vmware|vbox|i915|nouveau|amdgpu|fb" || echo "  None"
        echo ""

        echo "▶ X11 BINARIES:"
        which Xorg 2>/dev/null || echo "  Xorg not found!"
        which xinit 2>/dev/null || echo "  xinit not found!"
        which chromium 2>/dev/null || echo "  chromium not found!"
        echo ""

        echo "▶ SYSTEMD KIOSK SERVICE:"
        systemctl status secubox-kiosk.service --no-pager 2>&1 | head -20
        echo ""

        echo "▶ RELEVANT JOURNAL LOGS (last 50 lines):"
        journalctl -t secubox-kiosk --no-pager -n 50 2>/dev/null || echo "  No journal entries"
        echo ""

        echo "▶ XORG LOG (if exists):"
        tail -100 /var/log/Xorg.0.log 2>/dev/null || echo "  No Xorg.0.log yet"
        echo ""

        echo "═══════════════════════════════════════════════════════════════"
        echo "End of Debug Report"
        echo "═══════════════════════════════════════════════════════════════"
    } >> "$report" 2>&1

    log "Debug report written to: $report"

    # Also symlink as latest
    ln -sf "$report" /tmp/kiosk-debug-latest.log 2>/dev/null || true
}

# ══════════════════════════════════════════════════════════════════
# LOCK: Prevent .bash_profile's start-kiosk from running in parallel
# ══════════════════════════════════════════════════════════════════
readonly LOCK_FILE="/tmp/.kiosk-starting"

# Clean up stale lock files (PID no longer running or fresh boot)
if [[ -f "$LOCK_FILE" ]]; then
    old_pid=$(cat "$LOCK_FILE" 2>/dev/null || echo "")
    if [[ -n "$old_pid" ]] && kill -0 "$old_pid" 2>/dev/null; then
        log "Lock file exists - kiosk already starting/running (PID $old_pid)"
        exit 0
    else
        log "Removing stale lock file (old PID: $old_pid)"
        rm -f "$LOCK_FILE"
    fi
fi

# Create lock file with our PID
echo "$$" > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"' EXIT

# ══════════════════════════════════════════════════════════════════
# STEP 1: Verify prerequisites
# ══════════════════════════════════════════════════════════════════
check_prerequisites() {
    log "Checking prerequisites..."

    [[ -f /var/lib/secubox/.kiosk-enabled ]] || {
        err "Kiosk not enabled (/var/lib/secubox/.kiosk-enabled missing)"
        exit 1
    }

    # Ensure user exists
    if ! id "$KIOSK_USER" &>/dev/null; then
        log "Creating kiosk user..."
        useradd -m -d "$KIOSK_HOME" -s /bin/bash \
            -G video,audio,input,tty,render "$KIOSK_USER" 2>/dev/null || true
    fi

    log "Prerequisites OK"
}

# ══════════════════════════════════════════════════════════════════
# STEP 2: Detect VM and configure X11 driver
# Note: secubox-x11-setup.service runs before us and creates the config
#       This function is a fallback if that service didn't run
# ══════════════════════════════════════════════════════════════════
configure_x11() {
    log "Configuring X11..."

    # EARLY CHECK: If DRM works on bare metal, skip all config generation
    # This prevents corrupted configs from being created
    local vm_check
    vm_check=$(systemd-detect-virt 2>/dev/null | tr -d '\n\r' || echo "none")
    if [[ "$vm_check" == "none" ]] && ls /dev/dri/card* &>/dev/null 2>&1; then
        log "Bare metal with working DRM - using auto-detection (no config needed)"
        rm -f /etc/X11/xorg.conf.d/10-*.conf
        cat > /etc/X11/Xwrapper.config <<'XWRAP'
allowed_users=anybody
needs_root_rights=yes
XWRAP
        return 0
    fi

    # Check if secubox-x11-setup.service already created the config
    if [[ -f /etc/X11/xorg.conf.d/10-secubox-driver.conf ]]; then
        # Validate the config file syntax - Xorg -validate would be ideal but not always available
        # Simple check: ensure it has proper Section/EndSection pairs
        if grep -q "Parse error\|syntax error" /var/log/Xorg.0.log 2>/dev/null || \
           ! grep -q "EndSection" /etc/X11/xorg.conf.d/10-secubox-driver.conf 2>/dev/null; then
            log "WARNING: X11 config has errors - removing broken config"
            rm -f /etc/X11/xorg.conf.d/10-secubox-driver.conf
            rm -f /etc/X11/xorg.conf.d/10-*.conf
        else
            log "X11 config already exists (from secubox-x11-setup.service)"
            # Just ensure Xwrapper is configured
            cat > /etc/X11/Xwrapper.config <<'XWRAP'
allowed_users=anybody
needs_root_rights=yes
XWRAP
            return 0
        fi
    fi

    log "No X11 config found - creating one..."

    local vm_type driver="modesetting"
    vm_type=$(systemd-detect-virt 2>/dev/null | tr -d '\n\r' || echo "none")
    log "VM type: $vm_type"

    # Detect graphics hardware
    local gpu_info
    gpu_info=$(lspci 2>/dev/null | grep -iE "vga|display|3d" || echo "")
    log "GPU detected: $gpu_info"

    # PRIORITY 1: Use systemd-detect-virt for accurate VM detection
    # VirtualBox with VMSVGA shows as "VMware" in lspci but "oracle" in detect-virt
    if [[ "$vm_type" == "oracle" ]]; then
        # VirtualBox detected - VMSVGA (default) needs vmware driver
        if echo "$gpu_info" | grep -qi "SVGA\|VMware"; then
            driver="vmware"
            log "VirtualBox VMSVGA → vmware driver"
        else
            driver="modesetting"
            log "VirtualBox VBoxVGA → modesetting driver"
        fi
        modprobe vboxguest 2>/dev/null || true
        modprobe vboxvideo 2>/dev/null || true
    elif [[ "$vm_type" == "vmware" ]]; then
        driver="vmware"
        log "VMware detected → vmware driver"
        modprobe vmwgfx 2>/dev/null || true
    elif [[ "$vm_type" == "kvm" ]] || [[ "$vm_type" == "qemu" ]]; then
        driver="modesetting"
        log "KVM/QEMU detected → modesetting driver"
        modprobe virtio-gpu 2>/dev/null || true
    # PRIORITY 2: Fall back to lspci detection for bare metal or unknown VMs
    elif echo "$gpu_info" | grep -qi "VMware SVGA\|VMSVGA"; then
        driver="vmware"
        log "Detected VMSVGA graphics → vmware driver"
    elif echo "$gpu_info" | grep -qi "VirtualBox"; then
        driver="modesetting"
        log "Detected VirtualBox GPU → modesetting driver"
    elif echo "$gpu_info" | grep -qi "QXL\|Virtio"; then
        driver="modesetting"
        log "Detected QEMU/KVM → modesetting driver"
    elif echo "$gpu_info" | grep -qi "Intel"; then
        modprobe i915 2>/dev/null || true
        driver="modesetting"
        log "Detected Intel GPU → modesetting driver"
    elif echo "$gpu_info" | grep -qi "AMD\|ATI\|Radeon"; then
        modprobe amdgpu 2>/dev/null || modprobe radeon 2>/dev/null || true
        driver="modesetting"
        log "Detected AMD/ATI GPU → modesetting driver"
    elif echo "$gpu_info" | grep -qi "NVIDIA"; then
        modprobe nouveau 2>/dev/null || true
        driver="modesetting"
        log "Detected NVIDIA GPU → modesetting driver (nouveau)"
    elif [[ -d /dev/dri ]] && ls /dev/dri/card* 2>/dev/null; then
        driver="modesetting"
        log "DRM device found → modesetting driver"
    elif [[ -e /dev/fb0 ]]; then
        driver="fbdev"
        log "Framebuffer found → fbdev driver (fallback)"
    else
        driver="vesa"
        log "No GPU detected → vesa driver (safe mode)"
    fi

    # Clean existing configs that might cause issues
    rm -f /etc/X11/xorg.conf /etc/X11/xorg.conf.d/*.conf
    mkdir -p /etc/X11/xorg.conf.d

    # BARE METAL: Check if we have working DRM/GPU before relying on auto-detection
    if [[ "$vm_type" == "none" ]]; then
        log "Bare metal detected - checking GPU status..."

        # Try to load common GPU drivers if not already loaded
        modprobe i915 2>/dev/null || true
        modprobe amdgpu 2>/dev/null || true
        modprobe radeon 2>/dev/null || true
        modprobe nouveau 2>/dev/null || true
        sleep 1

        # Check if we have a working DRM device
        if ls /dev/dri/card* &>/dev/null; then
            log "DRM device found - auto-detection should work"
            driver="modesetting"
        elif [[ -e /dev/fb0 ]]; then
            log "No DRM but framebuffer exists - using fbdev"
            driver="fbdev"
        else
            log "No DRM/FB - trying VESA safe mode"
            driver="vesa"
        fi

        # Only skip config if DRM is working
        if ls /dev/dri/card* &>/dev/null; then
            log "DRM device found - skipping X11 config (auto-detection)"
            cat > /etc/X11/Xwrapper.config <<'XWRAP'
allowed_users=anybody
needs_root_rights=yes
XWRAP
            return 0
        fi
        # Otherwise fall through to create explicit config
        log "Creating explicit X11 config for bare metal (driver: $driver)"
    fi

    # VMs only: Write X11 config with explicit driver
    # Sanitize gpu_info to avoid special chars breaking the config
    local gpu_info_safe
    gpu_info_safe=$(echo "$gpu_info" | tr -d '<>()[]{}' | head -c 100)
    cat > /etc/X11/xorg.conf.d/10-kiosk.conf <<XCONF
# Generated by secubox-kiosk-launcher (VM mode)
# VM Type: $vm_type
# GPU: $gpu_info_safe
# Driver: $driver

Section "Device"
    Identifier "Kiosk Graphics"
    Driver "$driver"
EndSection

Section "Screen"
    Identifier "Kiosk Screen"
    Device "Kiosk Graphics"
    DefaultDepth 24
    SubSection "Display"
        Depth 24
        Modes "1920x1080" "1280x720" "1024x768" "800x600" "640x480"
    EndSubSection
    SubSection "Display"
        Depth 16
        Modes "1024x768" "800x600" "640x480"
    EndSubSection
EndSection

Section "ServerFlags"
    Option "DontZap" "false"
    Option "BlankTime" "0"
    Option "StandbyTime" "0"
    Option "SuspendTime" "0"
    Option "OffTime" "0"
    Option "AutoAddDevices" "true"
    Option "AllowEmptyInput" "false"
EndSection

Section "InputClass"
    Identifier "libinput keyboard"
    MatchIsKeyboard "on"
    Driver "libinput"
EndSection

Section "InputClass"
    Identifier "libinput pointer"
    MatchIsPointer "on"
    Driver "libinput"
EndSection

Section "InputClass"
    Identifier "libinput touchpad"
    MatchIsTouchpad "on"
    Driver "libinput"
EndSection
XCONF

    # Xwrapper permissions
    cat > /etc/X11/Xwrapper.config <<'XWRAP'
allowed_users=anybody
needs_root_rights=yes
XWRAP

    log "X11 configured with $driver driver"
}

# ══════════════════════════════════════════════════════════════════
# STEP 3: Determine kiosk URL
# ══════════════════════════════════════════════════════════════════
determine_url() {
    log "Determining kiosk URL..."

    local url=""
    # localhost first - always works regardless of network state
    local urls=(
        "https://localhost/"
        "https://127.0.0.1/"
        "http://localhost/"
        "http://127.0.0.1/"
    )

    # Wait for nginx (max 20s)
    for i in {1..20}; do
        systemctl is-active nginx &>/dev/null && break
        sleep 1
    done

    # Find working URL
    for test_url in "${urls[@]}"; do
        if curl -sk --connect-timeout 2 "$test_url" >/dev/null 2>&1; then
            url="$test_url"
            break
        fi
    done

    url="${url:-https://localhost/}"
    # Box neuve : l'assistant Premier Pas plutôt que le Hall (#1522). Il est
    # servi par le serveur par défaut : on garde l'adresse trouvée ci-dessus.
    local pp=""
    [ -x /usr/sbin/premier-pas-url ] && pp="$(/usr/sbin/premier-pas-url 2>/dev/null)"
    if [ -n "$pp" ]; then
        echo "${url%/}/$pp"
        return
    fi
    # LE KIOSQUE OUVRE L'ADMINISTRATION (#2534). Le Hall est une realisation propre a gk2, pas l'accueil de toute box : sur la console
    # locale (admin.localhost:9078, sans authentification pour le seul kiosque, #1695) puis sur le port ordinaire (9080), c'est le
    # tableau de bord SecuBox. KIOSK_START="hall" (dans /etc/default/secubox-kiosk) rend l'ancien comportement.
    local defauts="${KIOSK_DEFAUTS:-/etc/default/secubox-kiosk}" start="admin"
    if [ -r "$defauts" ]; then
        start="$(sed -n 's/^KIOSK_START="\{0,1\}\([a-z]*\)"\{0,1\}[[:space:]]*$/\1/p' "$defauts" | tail -1)"
        start="${start:-admin}"
    fi
    if [ "$start" = "admin" ]; then
        local aport page
        for aport in 9078 9080; do
            page="$(curl -s --connect-timeout 2 --max-time 5 --resolve "admin.localhost:$aport:127.0.0.1" "http://admin.localhost:$aport/" 2>/dev/null)" || continue
            if printf '%s' "$page" | grep -q '<title>SecuBox' && ! printf '%s' "$page" | grep -q 'id="featgrid"'; then
                echo "http://admin.localhost:$aport/"
                return
            fi
        done
    fi
    # Box configurée : LE HALL PAR SON PROPRE VHOST (#1668). Par localhost, le
    # serveur par défaut renvoie vers /hall/, copie montée dans la console où
    # les chemins absolus des cartes tombent sur l'administration. Chromium
    # résout *.localhost en boucle locale (contexte sûr) ; on ne le retient que
    # si c'est bien le Hall qui répond.
    # LA CONSOLE LOCALE D'ABORD (#1695) : le même Hall sur le port console,
    # où l'administration s'ouvre sans authentification pour ce seul kiosque
    # (l'auth vérifie que la connexion appartient à secubox-kiosk). Une box
    # dont le Hall n'écoute pas encore sur 9078 garde le port ordinaire.
    local port hall
    for port in 9078 9080; do
        hall="http://hall.localhost:$port/"
        if curl -s --connect-timeout 2 --max-time 5 --resolve "hall.localhost:$port:127.0.0.1" "$hall" 2>/dev/null \
             | grep -q 'id="featgrid"'; then
            url="$hall"
            break
        fi
    done
    echo "$url"
}

# ══════════════════════════════════════════════════════════════════
# STEP 4: Create kiosk session script (minimal, no optional deps)
# ══════════════════════════════════════════════════════════════════
create_session() {
    local url="$1"
    log "Creating kiosk session (URL: $url)..."

    mkdir -p "$KIOSK_HOME/.config"

    # Chromium profile directory
    mkdir -p "$KIOSK_HOME/.config/chromium"
    # Verrou de profil PÉRIMÉ : Chromium y inscrit le nom de la machine. Après
    # un renommage (Premier Pas), il croit le profil utilisé « sur un autre
    # ordinateur », refuse de démarrer, et le kiosque boucle jusqu'à l'échec
    # (vu sur gk3, #1544). Aucun Chromium du kiosque en vie = verrou périmé.
    if ! pgrep -u "$KIOSK_USER" -x chromium >/dev/null 2>&1; then
        rm -f "$KIOSK_HOME/.config/chromium/SingletonLock" \
              "$KIOSK_HOME/.config/chromium/SingletonCookie" \
              "$KIOSK_HOME/.config/chromium/SingletonSocket"
    fi
    chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config"

    # Detect if we're in a VM or on real hardware
    local vm_type chromium_gpu_flags
    vm_type=$(systemd-detect-virt 2>/dev/null | tr -d '\n' || echo "none")

    # --no-sandbox is always required on Debian 12: AppArmor restricts the
    # unprivileged user namespaces that chromium's zygote needs, regardless
    # of VM or bare-metal context. The kiosk runs as a dedicated unprivileged
    # secubox-kiosk user on an isolated VT in a closed-network appliance, so
    # the chromium sandbox provides marginal value vs. AppArmor's per-process
    # profile (which still applies). See issue #224.
    if [[ "$vm_type" == "none" ]]; then
        # Real hardware - enable GPU acceleration, drop sandbox for AppArmor
        chromium_gpu_flags="--no-sandbox --enable-features=VaapiVideoDecoder"
        log "Real hardware detected - GPU acceleration enabled, sandbox disabled (AppArmor)"
    else
        # VM - disable GPU to prevent crashes, drop sandbox (same reason)
        chromium_gpu_flags="--no-sandbox --disable-gpu --disable-gpu-compositing --disable-software-rasterizer"
        log "VM detected ($vm_type) - GPU disabled, sandbox disabled"
    fi

    # Write GPU flags for session to read
    echo "$chromium_gpu_flags" > "$KIOSK_HOME/.chromium-gpu-flags"
    chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.chromium-gpu-flags"

    # L'URL déterminée ICI, en root : la session tourne sous l'utilisateur du
    # kiosque, qui ne lit pas le jeton local de Premier Pas (0750 root:secubox).
    # Elle le reçoit par ce fichier, à lui seul (#1542).
    install -m 600 -o "$KIOSK_USER" -g "$KIOSK_USER" /dev/null "$KIOSK_HOME/.kiosk-url"
    printf '%s\n' "$url" > "$KIOSK_HOME/.kiosk-url"

    # Session script with simple splash and debug logging
    cat > "$KIOSK_HOME/.xsession" <<'XSESSION'
#!/bin/bash
# SecuBox Kiosk - X Session (v1.6.7.5)
exec >> /tmp/kiosk-session.log 2>&1
echo "=== X Session Start: $(date) ==="

export DISPLAY=${DISPLAY:-:0}
echo "DISPLAY=$DISPLAY"

# Log to syslog too
logger -t secubox-kiosk "X session starting on $DISPLAY"

# Disable screensaver
xset s off 2>/dev/null || echo "xset s off failed"
xset -dpms 2>/dev/null || echo "xset -dpms failed"
xset s noblank 2>/dev/null || echo "xset s noblank failed"

# Set dark background immediately
xsetroot -solid "#001100" 2>/dev/null || echo "xsetroot failed"
echo "Background set"

# DEBUG: Show visible status on screen using xmessage (non-blocking)
# This helps diagnose where the freeze happens
show_debug() {
    local msg="$1"
    echo "[DEBUG] $msg"
    logger -t secubox-kiosk "[DEBUG] $msg"
    # Show on screen if xmessage available
    if command -v xmessage &>/dev/null; then
        pkill -f "xmessage.*SecuBox" 2>/dev/null || true
        xmessage -center -timeout 3 -buttons "" "SecuBox: $msg" &
    fi
}

show_debug "X11 started, waiting for nginx..."

# SPLASH DISABLED - was causing freezes
# if [[ -x /usr/sbin/secubox-x11-splash ]]; then
#     /usr/sbin/secubox-x11-splash &
#     SPLASH_PID=$!
# fi

# Wait for nginx (max 15s) with visible feedback
echo "Waiting for nginx..."
for i in {1..15}; do
    if curl -sk --connect-timeout 1 https://localhost/ >/dev/null 2>&1; then
        echo "nginx ready after ${i}s"
        show_debug "nginx ready! Starting browser..."
        break
    fi
    # Change background color as visual progress indicator
    case $((i % 3)) in
        0) xsetroot -solid "#002200" 2>/dev/null ;;
        1) xsetroot -solid "#003300" 2>/dev/null ;;
        2) xsetroot -solid "#004400" 2>/dev/null ;;
    esac
    sleep 1
done

# Brief pause before Chromium
sleep 1

# Determine URL
URL="https://localhost/"
for test_url in "https://localhost/" "https://127.0.0.1/" "http://localhost/"; do
    if curl -sk --connect-timeout 2 "$test_url" >/dev/null 2>&1; then
        URL="$test_url"
        echo "URL found: $URL"
        break
    fi
done

# L'URL choisie par le lanceur (root), assistant Premier Pas compris (#1522,
# #1542) ; la détection ci-dessus ne sert que si le fichier manque.
[ -s "$HOME/.kiosk-url" ] && URL="$(head -n1 "$HOME/.kiosk-url")" && echo "URL du lanceur : ${URL%%#*}"

# Detect screen resolution for explicit window sizing
# xrandr returns something like "1920x1080+0+0" for connected displays
RESOLUTION=$(xrandr 2>/dev/null | grep -oP '\d+x\d+\+0\+0' | head -1 | cut -d'+' -f1)
if [[ -z "$RESOLUTION" ]]; then
    # Fallback: try to get from primary display
    RESOLUTION=$(xrandr 2>/dev/null | grep ' connected' | head -1 | grep -oP '\d+x\d+' | head -1)
fi
if [[ -z "$RESOLUTION" ]]; then
    RESOLUTION="1920x1080"  # Ultimate fallback
fi
WIDTH=$(echo "$RESOLUTION" | cut -dx -f1)
HEIGHT=$(echo "$RESOLUTION" | cut -dx -f2)
echo "Screen resolution: ${WIDTH}x${HEIGHT}"

logger -t secubox-kiosk "Launching Chromium: $URL (${WIDTH}x${HEIGHT})"
echo "Launching Chromium: $URL"

# Read GPU flags (set by launcher based on VM/hardware detection)
GPU_FLAGS=""
if [[ -f "$HOME/.chromium-gpu-flags" ]]; then
    GPU_FLAGS=$(cat "$HOME/.chromium-gpu-flags")
    echo "GPU flags: $GPU_FLAGS"
fi

# Rebuild font cache to ensure emoji fonts are registered
echo "Rebuilding font cache..."
fc-cache -f 2>/dev/null || echo "fc-cache failed (non-fatal)"

# Verify emoji font is available
if fc-list 2>/dev/null | grep -qi "noto.*emoji"; then
    echo "✓ Noto Color Emoji font available"
else
    echo "⚠ Emoji font not found - icons may appear as boxes"
fi

# Chromium kiosk mode
# --start-fullscreen instead of --kiosk (allows Escape to exit if stuck)
# GPU flags are dynamic based on hardware detection
# Font flags ensure proper emoji/Unicode rendering
exec chromium \
    --start-fullscreen \
    --window-size=${WIDTH},${HEIGHT} \
    --window-position=0,0 \
    --no-first-run \
    $GPU_FLAGS \
    --disable-background-networking \
    --disable-dev-shm-usage \
    --noerrdialogs \
    --disable-translate \
    --disable-features=Translate \
    --ignore-certificate-errors \
    --test-type \
    --disable-infobars \
    --disable-hang-monitor \
    --enable-features=UseOzonePlatform \
    --ozone-platform=x11 \
    --force-color-profile=srgb \
    "$URL"
XSESSION

    chmod +x "$KIOSK_HOME/.xsession"
    ln -sf .xsession "$KIOSK_HOME/.xinitrc"
    chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME"

    log "Session script created"
}

# ══════════════════════════════════════════════════════════════════
# STEP 5: Start X11 display
# Strategy: Start Xorg as root, then run session as kiosk user
# This is the most reliable approach for kiosk systems
# ══════════════════════════════════════════════════════════════════
start_display() {
    log "Starting X11 display..."

    local kiosk_uid kiosk_gid runtime_dir xauth_file x_log
    kiosk_uid=$(id -u "$KIOSK_USER")
    kiosk_gid=$(id -g "$KIOSK_USER")
    runtime_dir="/run/user/$kiosk_uid"
    xauth_file="$KIOSK_HOME/.Xauthority"
    x_log="/var/log/Xorg.0.log"

    # DEBUG: Log VM environment
    log "▶ VM Detection:"
    log "  - systemd-detect-virt: $(systemd-detect-virt 2>/dev/null || echo 'unknown')"
    log "  - /dev/dri contents: $(ls /dev/dri/ 2>/dev/null || echo 'empty')"
    log "  - DRM modules: $(lsmod | grep -E 'drm|vmware|vbox' 2>/dev/null | awk '{print $1}' | tr '\n' ' ')"

    # Setup XDG runtime directory
    mkdir -p "$runtime_dir"
    chown "$kiosk_uid:$kiosk_gid" "$runtime_dir"
    chmod 700 "$runtime_dir"

    # Create Xauthority with magic cookie
    log "Setting up Xauthority..."
    rm -f "$xauth_file"
    touch "$xauth_file"

    # Generate X auth cookie (mcookie or fallback)
    local cookie
    cookie=$(mcookie 2>/dev/null || od -An -tx1 -N16 /dev/urandom | tr -d ' \n')
    xauth -f "$xauth_file" add :0 . "$cookie" 2>/dev/null || true
    chown "$KIOSK_USER:$KIOSK_USER" "$xauth_file"
    chmod 600 "$xauth_file"
    log "Xauthority created"

    # Pre-flight checks
    log "Pre-flight checks:"
    log "  - User: $KIOSK_USER (uid=$kiosk_uid)"
    log "  - Xauthority: $xauth_file"
    log "  - Session: $KIOSK_HOME/.xsession"

    # Check X server
    if ! command -v Xorg >/dev/null 2>&1; then
        err "Xorg not found!"
        exit 1
    fi
    log "  - X server: $(which Xorg)"

    # Kill any existing X server
    pkill -9 Xorg 2>/dev/null || true
    pkill -9 X 2>/dev/null || true
    sleep 1

    log "Starting Xorg on :0 vt7..."

    # Start X server as root in background
    # -auth uses our Xauthority so kiosk user can connect
    # -noreset keeps X running even if last client disconnects
    Xorg :0 vt7 \
        -nolisten tcp \
        -auth "$xauth_file" \
        -noreset \
        -logfile "$x_log" \
        2>&1 &

    local x_pid=$!
    log "Xorg started with PID $x_pid"

    # Wait for X to be ready (check for socket)
    local attempts=0
    while [[ $attempts -lt 30 ]]; do
        if [[ -S /tmp/.X11-unix/X0 ]]; then
            log "X11 socket ready after ${attempts}s"
            break
        fi
        sleep 1
        ((attempts++))
    done

    # Verify X is running
    if ! kill -0 "$x_pid" 2>/dev/null; then
        track_failure
        err "Xorg process died! Check $x_log"
        err "▶ XORG FAILURE DEBUG:"
        {
            echo ""
            echo "════════ XORG FAILURE REPORT ════════"
            echo "Timestamp: $(date -Iseconds)"
            echo ""
            echo "▶ Xorg.0.log (last 100 lines):"
            tail -100 "$x_log" 2>/dev/null || echo "No log file"
            echo ""
            echo "▶ dmesg (graphics related):"
            dmesg 2>/dev/null | grep -iE "drm|gpu|vbox|vmware|display" | tail -30
            echo ""
            echo "▶ Kernel modules:"
            lsmod | grep -iE "drm|vbox|vmware|i915|nouveau" || echo "None found"
            echo ""
        } >> "$DEBUG_REPORT" 2>&1
        log "Debug info appended to: $DEBUG_REPORT"
        exit 1
    fi

    if [[ ! -S /tmp/.X11-unix/X0 ]]; then
        track_failure
        err "X11 socket not created after 30s"
        err "▶ X11 SOCKET DEBUG:"
        {
            echo ""
            echo "════════ X11 SOCKET FAILURE ════════"
            echo "Timestamp: $(date -Iseconds)"
            echo "Xorg PID: $x_pid ($(kill -0 $x_pid 2>&1 && echo 'running' || echo 'dead'))"
            echo ""
            echo "▶ /tmp/.X11-unix/:"
            ls -la /tmp/.X11-unix/ 2>/dev/null || echo "Directory doesn't exist"
            echo ""
            echo "▶ Xorg.0.log:"
            tail -100 "$x_log" 2>/dev/null || echo "No log file"
            echo ""
            echo "▶ VT status:"
            fgconsole 2>/dev/null && echo "(fgconsole)"
            cat /sys/class/tty/tty0/active 2>/dev/null && echo "(active tty)"
        } >> "$DEBUG_REPORT" 2>&1
        log "Debug info appended to: $DEBUG_REPORT"
        exit 1
    fi

    log "X server running, launching session as $KIOSK_USER..."

    # X started successfully - clear failure count
    clear_failures

    # Switch to VT7 explicitly
    chvt 7 2>/dev/null || true

    # Run the session as kiosk user
    # exec replaces this process - systemd keeps tracking the session
    exec su -s /bin/bash -l "$KIOSK_USER" -c "
        export DISPLAY=:0
        export XAUTHORITY='$xauth_file'
        export XDG_RUNTIME_DIR='$runtime_dir'
        export HOME='$KIOSK_HOME'
        cd '$KIOSK_HOME'
        exec '$KIOSK_HOME/.xsession'
    "
}

# ══════════════════════════════════════════════════════════════════
# MAIN
# ══════════════════════════════════════════════════════════════════
main() {
    # Console banner FIRST - visible to user before X starts
    echo ""
    echo "╔═══════════════════════════════════════════════════════════╗"
    echo "║       SecuBox Kiosk Launcher v3.3 (1.6.7.14)              ║"
    echo "╚═══════════════════════════════════════════════════════════╝"
    echo ""

    log "════════════════════════════════════════════════"
    log "SecuBox Kiosk Launcher v3.3 (1.6.7.14)"
    log "════════════════════════════════════════════════"

    # Show hardware info on console
    local vm_type platform_name gpu_info
    vm_type=$(systemd-detect-virt 2>/dev/null | tr -d '\n\r' || echo "none")
    if [[ "$vm_type" == "none" ]]; then
        platform_name="bare-metal (native)"
    else
        platform_name="$vm_type (VM)"
    fi
    gpu_info=$(lspci 2>/dev/null | grep -iE "vga|display" | head -1 || echo "unknown")

    echo "  Platform: $platform_name"
    echo "  GPU: $gpu_info"
    echo ""

    # Generate debug report for troubleshooting
    generate_debug_report

    check_prerequisites
    configure_x11

    local url
    url=$(determine_url)

    create_session "$url"

    echo "  Starting X11 on VT7..."
    echo "  (If screen stays black, press Ctrl+Alt+F1 for console)"
    echo ""

    start_display
}

main "$@"
