#!/bin/bash

# The Linux-only half of a restore: system packages, the bundled Ollama binary,
# and the XFCE desktop wiring (panel, wallpaper, theme, terminal, branding).
# None of it means anything on Windows, which is why it lives here instead of in
# bin/sync.py — sync.py owns the portable half and calls this in three stages:
#
#   restore-linux.sh prep      Before the rebuild: system packages the build needs.
#   restore-linux.sh runtime   After: Ollama binary + shell wiring. Any Linux box
#                              needs these to actually run NexusOS.
#   restore-linux.sh desktop   After: the XFCE look (panel, wallpaper, theme,
#                              branding). Cosmetic, this box's setup, and the only
#                              stage that rewrites files outside the repo and $HOME.
#                              Skippable with `--no-desktop`; auto-skipped off XFCE.
#
# Not meant to be run by hand — use `ncp restore` (python bin/sync.py restore).

# Set by bin/sync.py to the repo it was invoked from, so a clone in a scratch dir
# operates on itself instead of reaching into the real ~/nexus-core.
NEXUS_ROOT="${NEXUS_ROOT:-$HOME/nexus-core}"
stage="${1:?usage: restore-linux.sh prep|runtime|desktop}"
# sync.py calls these by name with check=False, so a stage renamed on one side
# and not the other would silently do nothing. Fail loudly instead; a test keeps
# this list and sync.py's call sites in agreement.
case "$stage" in
    prep|runtime|desktop) ;;
    *) echo "unknown stage: $stage (expected prep|runtime|desktop)" >&2; exit 2 ;;
esac
cd "$NEXUS_ROOT" || { echo "No $NEXUS_ROOT"; exit 1; }

if [ "$stage" = "prep" ]; then
    # Fresh machine: the system packages the desktop + build steps need. No-op once
    # installed, so it's cheap on an in-place restore. Skipped without apt (non-Debian).
    if command -v apt-get >/dev/null; then
        echo "Installing system packages..."

        # python3-venv is a transitional package pointing at the real
        # pythonX.Y-venv for whatever Python ships by default; on a distro ahead
        # of that transition it resolves to nothing ("has no installation
        # candidate") even though a real, version-suffixed package exists.
        # apt-cache show only succeeds for a package with an actual archive
        # entry, so it tells the two cases apart without guessing.
        venv_pkg="python3-venv"
        if command -v python3 >/dev/null && ! apt-cache show python3-venv >/dev/null 2>&1; then
            venv_pkg="python3-$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')-venv"
        fi

        pkgs="git sqlite3 curl $venv_pkg python3-gi gir1.2-gtk-3.0"
        # XFCE-only cosmetics: only worth attempting where there's an XFCE
        # session to plug into. Same signal the desktop stage below already
        # gates on, so a headless/WSL box (no xfconf-query) isn't left with
        # noisy "unable to locate package" failures for a panel it'll never run.
        if command -v xfconf-query >/dev/null; then
            pkgs="$pkgs xfce4-genmon-plugin plank blueman"
        fi

        # shellcheck disable=SC2086  # $pkgs is a deliberate word-split list
        sudo apt-get install -y --no-install-recommends $pkgs \
            || echo "Warning: some system packages failed — install them manually."

        # Node.js 20+: Vite needs 20.19+, but Debian/Ubuntu apt ship an EOL Node 18
        # (its 'nodejs' package) which crashes Vite with 'CustomEvent is not defined'.
        # Install from NodeSource only when the current node is missing or too old.
        node_major=$(node -v 2>/dev/null | sed -E 's/^v([0-9]+).*/\1/')
        if [ -z "$node_major" ] || [ "$node_major" -lt 20 ]; then
            echo "Installing Node.js 20 (found: ${node_major:-none})..."
            curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - \
                && sudo apt-get install -y nodejs \
                || echo "Warning: Node 20 install failed — install Node 20+ manually (Vite needs it)."
        fi
    fi
    exit 0
fi

if [ "$stage" = "runtime" ]; then
    echo ""
    echo "Ensuring Ollama binary..."
    # ollama/ is gitignored, so a fresh clone has no binary — fetch it. No-op if the
    # machine already has one (e.g. an in-place restore).
    if [ -x "$NEXUS_ROOT/bin/fetch-ollama.sh" ]; then
        "$NEXUS_ROOT/bin/fetch-ollama.sh" "$NEXUS_ROOT" || echo "Warning: Ollama fetch failed — install it manually."
    else
        echo "Warning: bin/fetch-ollama.sh not found — skipping Ollama fetch."
    fi

    # `ncp` on PATH, not a shell function: /usr/local/bin is visible to sh, cron,
    # systemd units and .desktop Exec lines, none of which read ~/.bashrc. The
    # Windows installer does the matching thing with management\ncp.cmd on PATH.
    # Falls back to the old ~/.bashrc function when there's no sudo (a shell
    # function shadows the symlink anyway, so having both is harmless).
    ncp_link="/usr/local/bin/ncp"
    ncp_target="$NEXUS_ROOT/management/nexus-cli.sh"
    if [ "$(readlink -f "$ncp_link" 2>/dev/null)" = "$ncp_target" ]; then
        echo "ncp already on PATH at $ncp_link."
    elif sudo ln -sfn "$ncp_target" "$ncp_link"; then
        echo "Registered ncp at $ncp_link."
    elif ! grep -q "management/nexus-cli.sh" "$HOME/.bashrc" 2>/dev/null; then
        # Guarded by a grep so an in-place restore is a no-op and a scratch clone
        # can't re-point an already-wired ~/.bashrc at itself.
        cat >> "$HOME/.bashrc" <<EOF

# Nexus
ncp() {
    $NEXUS_ROOT/management/nexus-cli.sh "\$@"
}
EOF
        echo "No sudo for $ncp_link — registered ncp in ~/.bashrc instead."
    fi

    if ! grep -qF "alias promethean=" "$HOME/.bashrc" 2>/dev/null; then
        printf "\n# Promethean\nalias promethean='source %s/.promethean_bashrc'\n" \
            "$NEXUS_ROOT" >> "$HOME/.bashrc"
        echo "Registered promethean in ~/.bashrc."
    fi

    # The AMD box runs CPU-only (Vega 20, 4GB VRAM thrashes). An NVIDIA box should not.
    if command -v nvidia-smi >/dev/null && command -v sqlite3 >/dev/null && \
       [ "$(sqlite3 "$NEXUS_ROOT/synapse/memory/memory.db" \
            "select value from settings where key='memory_gpu_offload'" 2>/dev/null)" = "0" ]; then
        echo "Note: memory_gpu_offload=0 came from the AMD box (4GB VRAM). This machine has an"
        echo "      NVIDIA GPU — raise it in Settings to actually use the card."
    fi
    exit 0
fi

# --- desktop stage: XFCE only, and it writes outside the repo -----------------
# Everything below reconfigures the logged-in user's desktop. On any other DE it
# would be actively wrong (copying XFCE channel XMLs onto a GNOME box does
# nothing good), so bail rather than make a mess of someone else's machine.
if ! command -v xfconf-query >/dev/null; then
    echo "Not an XFCE session (no xfconf-query) — skipping desktop wiring."
    exit 0
fi

# Panel layout, wallpaper, compositing, keybindings and terminal profile all live
# in the xfconf channel XMLs — restore them by copying the files back. xfconfd
# caches channels in memory and rewrites them on exit, so it has to die first or
# it clobbers what we just copied; the next xfconf-query respawns it.
xml_snap="$NEXUS_ROOT/assets/themes/restore-snapshot/xfconf-xml"
xml_dst="$HOME/.config/xfce4/xfconf/xfce-perchannel-xml"
if [ -d "$xml_snap" ]; then
    echo ""
    echo "Restoring XFCE desktop settings (panel, wallpaper, effects)..."
    mkdir -p "$xml_dst"
    pkill -x xfconfd 2>/dev/null && sleep 1
    cp -f "$xml_snap"/*.xml "$xml_dst/" 2>/dev/null

    # Wallpaper props are keyed by monitor name, which differs per machine — point
    # every backdrop this box actually has at the Nexus background.
    bg="$NEXUS_ROOT/assets/background.png"
    if [ -f "$bg" ] && [ -n "${DISPLAY:-}" ]; then
        xfconf-query -c xfce4-desktop -l 2>/dev/null | grep 'last-image$' | while read -r p; do
            xfconf-query -c xfce4-desktop -p "$p" -s "$bg" 2>/dev/null || true
        done
    fi
fi

# Multi-monitor primary-follow watcher (panel + Plank track the xrandr primary).
if [ -f "$NEXUS_ROOT/bin/panel/plank-primary-watch.sh" ]; then
    mkdir -p "$HOME/.local/bin"
    chmod +x "$NEXUS_ROOT/bin/panel/plank-primary-watch.sh"
    ln -sf "$NEXUS_ROOT/bin/panel/plank-primary-watch.sh" "$HOME/.local/bin/plank-primary-watch.sh"
fi
plank_snap="$NEXUS_ROOT/assets/themes/restore-snapshot/plank"
if [ -d "$plank_snap" ]; then
    mkdir -p "$HOME/.config/plank"
    cp -rf "$plank_snap/." "$HOME/.config/plank/"   # /. = contents, else it nests
fi

echo ""
echo "Restoring NexusOS desktop theme..."
theme_installer="$NEXUS_ROOT/assets/themes/install-theme.sh"
if [ -x "$theme_installer" ]; then
    "$theme_installer"
elif [ -f "$theme_installer" ]; then
    bash "$theme_installer"
else
    echo "Warning: $theme_installer not found — skipping theme restore."
fi

echo ""
echo "Installing Promethean Terminal launcher..."
term_installer="$NEXUS_ROOT/bin/promethean/install.sh"
if [ -x "$term_installer" ]; then
    "$term_installer"
else
    echo "Warning: $term_installer not found — skipping."
fi

echo ""
echo "Installing panel applet..."
panel_installer="$NEXUS_ROOT/bin/panel/install.sh"
if [ -x "$panel_installer" ]; then
    "$panel_installer"
else
    echo "Warning: $panel_installer not found — skipping panel install."
fi

# Boot branding — the Plymouth splash. Not XFCE-specific, but it's cosmetic and
# writes outside the repo, so it belongs to the skippable stage like os-release
# below. Self-skips when the theme is already installed (initramfs rebuild is slow).
if [ -x "$NEXUS_ROOT/bin/boot-branding.sh" ]; then
    echo ""
    echo "Installing NexusOS boot branding (splash + greeter)..."
    sudo "$NEXUS_ROOT/bin/boot-branding.sh" || echo "Warning: boot branding skipped."
fi

# Distro branding — the About dialog / neofetch read /etc/os-release.
if grep -q '^ID=linuxmint' /etc/os-release 2>/dev/null && ! grep -q 'NexusOS' /etc/os-release; then
    echo ""
    echo "Branding /etc/os-release as NexusOS..."
    sudo sed -i -e 's/^NAME=.*/NAME="NexusOS"/' -e 's/^PRETTY_NAME=.*/PRETTY_NAME="NexusOS 1.0"/' \
        /etc/os-release || echo "Warning: os-release branding skipped."
fi
