#!/bin/bash

# Exit on error
set -e

# Mark a .desktop file as trusted via gio metadata, executed as $TARGET_USER
# within their D-Bus session. Best-effort: silently skips if gio is missing
# or the user has no active session bus.
#
# Required by GNOME Shell "Desktop Icons NG" (Ubuntu 22.04+) in addition to
# the executable bit. chmod +x alone doesn't satisfy the trust check there.
mark_trusted_gio() {
    local file="$1"
    local target_user="$2"

    [ -z "$file" ] && return 0
    [ -z "$target_user" ] && return 0
    [ "$target_user" = "root" ] && return 0

    command -v gio &>/dev/null || return 0

    local target_uid
    target_uid=$(id -u "$target_user" 2>/dev/null) || return 0
    local dbus_addr="unix:path=/run/user/${target_uid}/bus"

    # Runtime dir must exist, otherwise the session bus isn't active.
    [ -S "/run/user/${target_uid}/bus" ] || return 0

    if [ "$(id -u)" -eq "$target_uid" ]; then
        DBUS_SESSION_BUS_ADDRESS="$dbus_addr" \
            gio set "$file" metadata::trusted true 2>/dev/null || true
    else
        sudo -u "$target_user" \
            DBUS_SESSION_BUS_ADDRESS="$dbus_addr" \
            gio set "$file" metadata::trusted true 2>/dev/null || true
    fi
}

# Detect the hardware model from kernel/firmware sources in priority order:
#   1. /proc/board                        (kernel-provided, most authoritative)
#   2. /proc/device-tree/board/board-type (device-tree firmware value)
#   3. /etc/board                         (user-configured persistent value, read-only)
# Mirrors the Go ReadDeviceModel logic. /etc/board is never written by the installer —
# only honored if pre-placed by an operator.
detect_hw_model() {
    local model=""
    for src in /proc/board /proc/device-tree/board/board-type /etc/board; do
        if [ -f "$src" ]; then
            # Strip NUL bytes (device-tree files are NUL-terminated) and all
            # whitespace anywhere (spaces, tabs, line endings). Example:
            # "ADV ECU-579\n\x00" -> "ADVECU-579".
            local val
            val=$(tr -d '\0\t\n\r\v\f ' < "$src")
            if [ -n "$val" ] && [ "${#val}" -le 100 ]; then
                model="$val"
                break
            fi
        fi
    done
    [ -z "$model" ] && model="ADVANTECH-EDGE"
    echo "$model"
}

# Persist the detected hardware model to /opt/Advantech/dmagent/res/board for
# external consumers (other dmagent components, support diagnostics).
# Skips the ADVANTECH-EDGE sentinel so an unknown value isn't cached.
persist_hw_model() {
    local model="$1"
    [ -z "$model" ] && return 0
    [ "$model" = "ADVANTECH-EDGE" ] && return 0
    sudo mkdir -p /opt/Advantech/dmagent/res 2>/dev/null || true
    echo "$model" | sudo tee /opt/Advantech/dmagent/res/board > /dev/null 2>&1 || true
}

APP_NAME="weda-node-activator"
# The path requested by the user for the binary
INSTALL_BASE="/opt/Advantech/dmagent"
INSTALL_DIR="$INSTALL_BASE/weda-node-activator"
BINARY_DEST="$INSTALL_DIR/bin/$APP_NAME"

# Verify all critical desktop-icon infrastructure files landed correctly.
# Runs at the end of installation to guarantee BSP images never ship without
# working launchers. Exits the caller with status 1 if anything is missing.
verify_install() {
    echo "[Step 4] Verifying installation..."
    local missing=0

    local must_exist_exec=(
        "$BINARY_DEST"
        "/opt/Advantech/dmagent/scripts/setup-desktop-icons.sh"
        "/etc/skel/Desktop/weda-node.desktop"
        "/etc/skel/Desktop/weda-intro.desktop"
        "/etc/skel/Desktop/weda-learninghub.desktop"
        "/etc/xdg/autostart/weda-desktop-setup.desktop"
    )
    local must_exist=(
        "/usr/share/applications/weda-node.desktop"
        "/usr/share/applications/weda-intro.desktop"
        "/usr/share/applications/weda-learninghub.desktop"
    )

    local f
    for f in "${must_exist_exec[@]}"; do
        if [ ! -f "$f" ]; then
            echo "  [FAIL] Missing: $f" >&2
            missing=$((missing + 1))
        elif [ ! -x "$f" ]; then
            echo "  [FAIL] Not executable: $f" >&2
            missing=$((missing + 1))
        else
            echo "  [OK]   $f"
        fi
    done

    for f in "${must_exist[@]}"; do
        if [ ! -f "$f" ]; then
            echo "  [FAIL] Missing: $f" >&2
            missing=$((missing + 1))
        else
            echo "  [OK]   $f"
        fi
    done

    if [ "$missing" -gt 0 ]; then
        echo "Error: $missing critical file(s) missing or non-executable — installation is incomplete." >&2
        return 1
    fi
    echo "All critical files verified."
}

echo "--- WEDA Node Installer for Ubuntu (x64) ---"

echo "[Step 1] Verifying System & Runtime Environment..."

if command -v sudo &> /dev/null; then
    echo "  [OK]   sudo is available."
elif command -v su &> /dev/null; then
    echo "  [OK]   su is available."
else
    echo "  [FAIL] Neither sudo nor su found. Root access is required to install."
    exit 1
fi
echo ""

echo "[Step 2] Locating Installation Package..."

# Find the tar.gz package (x64, online or offline variant).
# We look in 'dist' (local dev) or current directory (installer package).
PACKAGE_FILE=$(find . -maxdepth 2 -name "weda-node-activator-*-linux-x64-*.tar.gz" -type f -print -quit)

if [ -z "$PACKAGE_FILE" ]; then
    # Fallback: legacy naming without variant suffix
    PACKAGE_FILE=$(find . -maxdepth 2 -name "weda-node-activator-*-linux-x64.tar.gz" -type f -print -quit)
fi

if [ -z "$PACKAGE_FILE" ]; then
    echo "Error: No 'weda-node-activator-*-linux-x64-*.tar.gz' package found in 'dist/' or current directory."
    echo "Please build the package first (e.g., './script/build.sh --platform linux/amd64')."
    exit 1
fi

echo "Found package: $PACKAGE_FILE"

echo "[Step 3] Installing to $INSTALL_DIR..."

# Ensure target directories exist
# We use sudo for /opt writes
if ! sudo mkdir -p "$INSTALL_DIR/bin"; then
    echo "Error: Failed to create installation directory $INSTALL_DIR/bin"
    exit 1
fi

# Create a temporary directory for extraction
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT

# Extract to temp dir
echo "Extracting package..."
if ! tar -xzf "$PACKAGE_FILE" -C "$TEMP_DIR"; then
    echo "Error: Failed to extract $PACKAGE_FILE"
    exit 1
fi

# Find the binary inside the extracted folder (it's inside a versioned folder)
EXTRACTED_BINARY=$(find "$TEMP_DIR" -name "$APP_NAME" -type f -print -quit)

if [ -z "$EXTRACTED_BINARY" ]; then
    echo "Error: Could not find binary '$APP_NAME' inside the package."
    exit 1
fi

# Move binary to final destination
echo "Installing binary to $BINARY_DEST..."
if ! sudo mv "$EXTRACTED_BINARY" "$BINARY_DEST"; then
    echo "Error: Failed to move binary to destination."
    exit 1
fi

# Set executable permissions
sudo chmod +x "$BINARY_DEST"

# Define PACKAGE_DIR for subsequent steps
PACKAGE_DIR=$(dirname "$PACKAGE_FILE")

echo "[Step 3.1] Installing system files from rootfs/usr..."
ROOTFS_USR=""
if [ -d "$PACKAGE_DIR/rootfs/usr" ]; then
    ROOTFS_USR="$PACKAGE_DIR/rootfs/usr"
else
    ROOTFS_USR=$(find "$TEMP_DIR" -type d -path "*/rootfs/usr" -print -quit 2>/dev/null)
fi
if [ -z "$ROOTFS_USR" ]; then
    echo "Error: rootfs/usr not found in package." >&2
    echo "       Desktop launchers and icons require this directory. Ensure the unified installer" >&2
    echo "       package is used (produced by create_unified_installer.sh)." >&2
    exit 1
fi
if ! sudo cp -a "$ROOTFS_USR/." /usr/; then
    echo "Error: Failed to copy rootfs/usr files to /usr/" >&2
    exit 1
fi
echo "System files installed successfully to /usr/"

echo "[Step 3.1b] Installing config files from rootfs/opt..."
ROOTFS_OPT=""
if [ -d "$PACKAGE_DIR/rootfs/opt" ]; then
    ROOTFS_OPT="$PACKAGE_DIR/rootfs/opt"
else
    ROOTFS_OPT=$(find "$TEMP_DIR" -type d -path "*/rootfs/opt" -print -quit 2>/dev/null)
fi
if [ -z "$ROOTFS_OPT" ]; then
    echo "Error: rootfs/opt not found in package (setup-desktop-icons.sh missing)." >&2
    exit 1
fi
if ! sudo cp -a "$ROOTFS_OPT/." /opt/; then
    echo "Error: Failed to copy rootfs/opt files to /opt/" >&2
    exit 1
fi
echo "Config files installed successfully to /opt/"
# Ensure shell scripts shipped under /opt/Advantech/ are executable.
sudo find /opt/Advantech -type f -name '*.sh' -exec chmod 755 {} + 2>/dev/null || true

echo "[Step 3.1c] Installing desktop launchers from rootfs/etc..."
# Uses an explicit allow-list of paths we own so future additions under
# rootfs/etc/ can never silently land in production /etc/. 'install -D -m 0755'
# creates parent dirs and sets mode atomically (no separate chmod needed).
ROOTFS_ETC=""
if [ -d "$PACKAGE_DIR/rootfs/etc" ]; then
    ROOTFS_ETC="$PACKAGE_DIR/rootfs/etc"
else
    ROOTFS_ETC=$(find "$TEMP_DIR" -type d -path "*/rootfs/etc" -print -quit 2>/dev/null)
fi
if [ -z "$ROOTFS_ETC" ]; then
    echo "Error: rootfs/etc not found in package (desktop launcher templates missing)." >&2
    exit 1
fi
ETC_FILES=(
    "skel/Desktop/weda-node.desktop"
    "skel/Desktop/weda-intro.desktop"
    "skel/Desktop/weda-learninghub.desktop"
    "xdg/autostart/weda-desktop-setup.desktop"
)
for rel in "${ETC_FILES[@]}"; do
    src="$ROOTFS_ETC/$rel"
    dst="/etc/$rel"
    if [ ! -f "$src" ]; then
        echo "Error: Missing expected file in rootfs/etc: $rel" >&2
        exit 1
    fi
    if ! sudo install -D -m 0755 "$src" "$dst"; then
        echo "Error: Failed to install $dst" >&2
        exit 1
    fi
done
echo "Desktop launcher templates installed to /etc/"

# Also deploy the icons directly into the target user's Desktop. Resolution
# order:
#   1. WEDA_TARGET_USER  — explicit override, used by BSP/chroot flows (x64
#                          rootfs builds) where SUDO_USER is absent because
#                          the installer runs as root inside the chroot.
#                          Optional companion: WEDA_TARGET_HOME overrides the
#                          home path when /etc/passwd inside the chroot does
#                          not yet reflect the final layout.
#   2. SUDO_USER         — normal `sudo ./installer.sh` on a running device.
#   3. current non-root  — running the installer directly as an unprivileged
#                          user that happens to have write access (rare).
# When none apply (plain root, no BSP env var), we fall through to the
# /etc/skel path — any user created afterwards will pick the icons up at
# useradd time, and the /etc/xdg/autostart unit covers existing users on
# first GNOME login.
BSP_MODE=0
if [ -n "${WEDA_TARGET_USER:-}" ] && [ "$WEDA_TARGET_USER" != "root" ]; then
    TARGET_USER="$WEDA_TARGET_USER"
    if [ -n "${WEDA_TARGET_HOME:-}" ]; then
        TARGET_HOME="$WEDA_TARGET_HOME"
    else
        TARGET_HOME=$(getent passwd "$TARGET_USER" 2>/dev/null | cut -d: -f6)
    fi
    if [ -z "$TARGET_HOME" ]; then
        echo "Error: WEDA_TARGET_USER=$TARGET_USER not found in /etc/passwd and WEDA_TARGET_HOME not set." >&2
        echo "       Create the user first or export WEDA_TARGET_HOME=/home/$TARGET_USER." >&2
        exit 1
    fi
    BSP_MODE=1
elif [ -n "${SUDO_USER:-}" ] && [ "$SUDO_USER" != "root" ]; then
    TARGET_USER="$SUDO_USER"
    TARGET_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
elif [ "$(id -u)" -ne 0 ]; then
    TARGET_USER="$(id -un)"
    TARGET_HOME="$HOME"
else
    TARGET_USER=""
    TARGET_HOME=""
fi

# In BSP mode we create the home/Desktop tree even if it doesn't exist yet —
# a chroot rootfs may not have a populated home for the default user at
# build time. For a live device we require the home to exist already
# (safer: avoids accidentally creating an empty /home/foo on a typo).
if [ -n "$TARGET_USER" ] && { [ "$BSP_MODE" -eq 1 ] || [ -d "$TARGET_HOME" ]; }; then
    if [ "$BSP_MODE" -eq 1 ]; then
        echo "[Step 3.1d] BSP mode: deploying desktop icons to $TARGET_HOME/Desktop/ for user '$TARGET_USER'..."
    else
        echo "[Step 3.1d] Deploying desktop icons to $TARGET_HOME/Desktop/..."
    fi

    TARGET_UIDGID=$(getent passwd "$TARGET_USER" 2>/dev/null | awk -F: '{printf "%s:%s", $3, $4}')
    if [ -z "$TARGET_UIDGID" ]; then
        # User must exist — chown by name would fail silently in chroot on
        # some nss configurations. Numeric uid:gid is portable.
        echo "Error: Unable to resolve uid/gid for $TARGET_USER (not in /etc/passwd)." >&2
        exit 1
    fi

    sudo install -d -m 0755 -o "${TARGET_UIDGID%:*}" -g "${TARGET_UIDGID#*:}" "$TARGET_HOME/Desktop"
    for f in weda-node.desktop weda-intro.desktop weda-learninghub.desktop; do
        if [ -f "/etc/skel/Desktop/$f" ]; then
            sudo install -m 0755 -o "${TARGET_UIDGID%:*}" -g "${TARGET_UIDGID#*:}" \
                "/etc/skel/Desktop/$f" "$TARGET_HOME/Desktop/$f"
            # Mark trusted via gio metadata if the user has an active
            # D-Bus session. Always a no-op in BSP/chroot — the
            # /etc/xdg/autostart unit re-marks trusted on first login.
            if [ "$BSP_MODE" -eq 0 ]; then
                mark_trusted_gio "$TARGET_HOME/Desktop/$f" "$TARGET_USER"
            fi
        fi
    done

    if [ "$BSP_MODE" -eq 1 ]; then
        echo "  Icons pre-deployed; gio trust-marking will run on first GNOME login via"
        echo "  /etc/xdg/autostart/weda-desktop-setup.desktop."
    fi
fi

# Copy docker-compose.template.yml to INSTALL_BASE if it exists
echo "[Step 3.2] Setting up docker-compose configuration..."
if [ -f "$PACKAGE_DIR/docker-compose.template.yml" ]; then
    echo "Installing docker-compose.yml from template..."
    if ! sudo cp "$PACKAGE_DIR/docker-compose.template.yml" "$INSTALL_BASE/docker-compose.yml"; then
        echo "Warning: Failed to copy docker-compose.template.yml to $INSTALL_BASE/"
    else
        echo "docker-compose.yml installed successfully to $INSTALL_BASE/"
    fi
elif [ -f "$TEMP_DIR/"*"/docker-compose.template.yml" ]; then
    # Check in extracted temp directory
    DOCKER_COMPOSE_TEMPLATE=$(find "$TEMP_DIR" -type f -name "docker-compose.template.yml" -print -quit)
    if [ -n "$DOCKER_COMPOSE_TEMPLATE" ]; then
        echo "Installing docker-compose.yml from template..."
        if ! sudo cp "$DOCKER_COMPOSE_TEMPLATE" "$INSTALL_BASE/docker-compose.yml"; then
            echo "Warning: Failed to copy docker-compose.template.yml to $INSTALL_BASE/"
        else
            echo "docker-compose.yml installed successfully to $INSTALL_BASE/"
        fi
    fi
fi

# Stage Docker images tarball for the wizard to load via 'docker load'.
echo "[Step 3.3] Staging Docker images..."
IMAGES_TARBALL=""
if [ -f "$PACKAGE_DIR/weda-images.tar.gz" ]; then
    IMAGES_TARBALL="$PACKAGE_DIR/weda-images.tar.gz"
else
    IMAGES_TARBALL=$(find "$TEMP_DIR" -maxdepth 2 -name "weda-images.tar.gz" -type f -print -quit 2>/dev/null)
fi

if [ -n "$IMAGES_TARBALL" ]; then
    if sudo cp "$IMAGES_TARBALL" "$INSTALL_BASE/weda-images.tar.gz"; then
        echo "Image tarball staged at $INSTALL_BASE/weda-images.tar.gz"
    else
        echo "Warning: Failed to stage Docker image tarball."
    fi
else
    echo "Warning: No weda-images.tar.gz found in package. Images must be pulled manually."
fi

echo "[Step 3.4] Detecting hardware model..."
HW_MODEL=$(detect_hw_model)
echo "Hardware model: $HW_MODEL"
persist_hw_model "$HW_MODEL"

# Note: application launchers (.desktop files) are deployed to
# /usr/share/applications/ by the wizard itself (installRootFS). They are
# system-trusted and appear in the GNOME app grid (Super key → "WEDA").

# Post-install verification — guarantees BSP images never ship with broken
# or missing desktop-icon infrastructure.
verify_install || exit 1

# --- Install the uninstaller onto the device ---
# Ships in the package; placed under /usr/local/bin (outside the /opt/Advantech
# tree it removes) so the node can be cleanly uninstalled later:
#   sudo uninstall_weda.sh --dry-run   (preview)
#   sudo uninstall_weda.sh --yes       (full removal)
INSTALL_SH_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ -f "$INSTALL_SH_DIR/uninstall_weda.sh" ]; then
    if mkdir -p /usr/local/bin 2>/dev/null && \
       cp "$INSTALL_SH_DIR/uninstall_weda.sh" /usr/local/bin/uninstall_weda.sh 2>/dev/null; then
        chmod +x /usr/local/bin/uninstall_weda.sh
        echo "Uninstaller installed: /usr/local/bin/uninstall_weda.sh"
    else
        echo "Note: /usr/local/bin not writable; uninstaller left in package only."
    fi
fi

echo "--- Installation Complete ---"
echo "Installed version from: $(basename "$PACKAGE_FILE")"
echo "Location: $BINARY_DEST"
echo "Run the WEDA Node Activator by pressing Super and searching for 'WEDA Node Activator'."
