#!/bin/bash
# Install or update Claude Desktop (official Linux build, arm64) without apt:
# fetch the latest .deb from Anthropic's apt repo, verify its SHA256 and unpack
# it into ~/.local/opt. Safe to re-run; does nothing when already current. Refuses while
# Claude Desktop is open unless given --restart.
set -euo pipefail
REPO=https://downloads.claude.ai/claude-desktop/apt/stable
OPT="$HOME/.local/opt/claude-desktop"
# Translations (lib/i18n.sh; the copy install_i18n puts here), else English
# shellcheck source=/dev/null
source "$HOME/.local/share/frame-tweaks/i18n/i18n.sh" 2>/dev/null ||
    t() { local f=$1; shift; if [ $# -eq 0 ]; then printf '%s' "$f"; else printf -- "$f" "$@"; fi; }
# (a time limit: a stalled connection hung the install's terminal for good)
P=$(curl -fsSL --max-time 60 --retry 2 --retry-delay 3 "$REPO/dists/stable/main/binary-arm64/Packages")
VER=$(echo "$P" | grep ^Version: | sort -V -k2 | tail -1 | cut -d' ' -f2)
BLOCK=$(echo "$P" | awk -v v="$VER" '/^Package:/{b=""} {b=b $0 "\n"} /^$/ && b ~ "Version: " v "\n" {print b; exit} END{if (b ~ "Version: " v "\n") print b}')
F=$(echo "$BLOCK" | grep ^Filename: | head -1 | cut -d' ' -f2)
H=$(echo "$BLOCK" | grep ^SHA256: | head -1 | cut -d' ' -f2)
# A launcher, not a link to the program: every start (app menu, VR "+" menu, a claude:// link, a
# terminal) uses the shared KDE wallet. Started without it, Claude can't encrypt (backend
# basic_text), never keeps your sign-in, and can't read one saved by a wallet-backed start.
# Written even when Claude is already current, so re-running this fixes an older install.
mkdir -p "$HOME/.local/bin"; rm -f "$HOME/.local/bin/claude-desktop"
cat > "$HOME/.local/bin/claude-desktop" <<'LAUNCHER'
#!/bin/sh
# Claude Desktop, always with the shared KDE wallet (see claude-desktop-update in frame-tweaks).
case " $* " in *" --password-store="*) ;; *) set -- --password-store=kwallet6 "$@" ;; esac
outer="$HOME/.local/bin/frame-outer-bus"     # the wallet's session bus (wallet/), if installed
[ -x "$outer" ] || outer=
exec $outer "$HOME/.local/opt/claude-desktop/claude-desktop" "$@"
LAUNCHER
chmod 755 "$HOME/.local/bin/claude-desktop"
CUR=$(cat "$OPT/.deb-version" 2>/dev/null || echo none)
[ "$VER" = "$CUR" ] && { t 'Claude Desktop already at %s' "$VER"; echo; exit 0; }

# Never close a running Claude Desktop without being asked (you could lose an unsent message).
if pgrep -f "^$OPT/claude-desktop" >/dev/null && [ "${1:-}" != --restart ]; then
    t 'Claude Desktop %s is available, but Claude Desktop is open: quit it first,
or run: claude-desktop-update --restart   (closes it, updates, and you reopen it)' "$VER"; echo
    exit 3
fi
T=$(mktemp -d); trap 'rm -rf "$T"' EXIT
echo "Claude Desktop: $CUR -> $VER"
curl -fL# --retry 3 --retry-all-errors --retry-delay 3 -o "$T/pkg.deb" "$REPO/$F"
echo "$H  $T/pkg.deb" | sha256sum -c --quiet
bsdtar -xf "$T/pkg.deb" -C "$T" data.tar.xz && mkdir "$T/root" && tar -xf "$T/data.tar.xz" -C "$T/root"
pkill -f "^$OPT/" || true          # only reached when it isn't running, or with --restart
# (copied beside it first, then swapped in: deleted first, a copy that failed (disk full) left no
# Claude Desktop at all)
mkdir -p "$(dirname "$OPT")" && rm -rf "$OPT.new" && cp -a "$T/root/usr/lib/claude-desktop" "$OPT.new" &&
    rm -rf "$OPT" && mv "$OPT.new" "$OPT" || { rm -rf "$OPT.new"; exit 1; }
echo "$VER" > "$OPT/.deb-version"

mkdir -p "$HOME/.local/bin" "$HOME/.local/share/applications" "$HOME/.local/share/icons"
cp -a "$T/root/usr/share/icons/hicolor" "$HOME/.local/share/icons/"
ORIG="$HOME/.local/share/frame-tweaks/launcher-originals"   # wallet-launcher's originals
BUILT="$HOME/.local/share/frame-tweaks/menu-built"          # each entry as written (lib/menuedits.py)
mkdir -p "$BUILT"
for d in "$T"/root/usr/share/applications/*.desktop; do
    name=$(basename "$d") dest="$HOME/.local/share/applications/$(basename "$d")"
    entry=$(sed "s|^Exec=claude-desktop|Exec=$HOME/.local/bin/claude-desktop|" "$d")
    if [ -f "$ORIG/$name" ]; then
        # Routed to the shared wallet (wallet/): refresh the original, then re-wrap it.
        printf '%s\n' "$entry" > "$ORIG/$name"
        "$HOME/.local/bin/wallet-launcher" "${name%.desktop}"
    else
        # (what you've changed in it since it was last written stays: a new name or icon)
        mine=$(printf '%s\n' "$entry" | python3 "$HOME/.local/share/frame-tweaks/i18n/menuedits.py" keep "$dest" \
            "$BUILT/$name" 2>/dev/null) && [ -n "$mine" ] || mine=$entry
        printf '%s\n' "$mine" > "$dest"
    fi
    printf '%s\n' "$entry" > "$BUILT/$name"
done
update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
t "Done. Launch 'Claude' from the app menu."; echo
