#!/usr/bin/env bash
# Refresh the rehydrate backups held in codeserver-setup/ from the live container.
#
# No root needed. Run it whenever you like (Claude can run it too):
#
#   bash /config/workspace/codeserver-setup/backup.sh
#
# install.sh calls it at the end of every run, after its restores.
#
# What it backs up (live -> codeserver-setup/):
#   memory-seed/            Claude memory (adds and updates; never deletes)
#   state/                  dotfiles and editor config that live outside the mounts
#   state/secrets/          /config/secrets (prod log sync) + HubSpot CLI config
#   state/browser-tools/    tarball snapshots of browser-tools scripts and .env
#
# Only /config/.claude and /config/workspace survive a container recreate.
# Everything else under /config sits in the container layer and is wiped.
#
# /config/workspace is ALSO the web root of shane.evolutionerp.com.au, which is
# public. Anything here that www-data can read can be downloaded, so this script
# keeps backup folders at 0700 and secret files at 0600 (Apache then returns 403).
#
# Missing live sources never clobber a backup: a fresh container that has not
# been rehydrated yet cannot wipe state/ by running this.

set -euo pipefail
umask 077

HERE="$(cd "$(dirname "$0")" && pwd)"
STATE_DIR="$HERE/state"
MEMORY_DIR="/config/.claude/projects/-config-workspace/memory"
MEMORY_SEED="$HERE/memory-seed"
BROWSER_TOOLS="/config/workspace/browser-tools"
SNAP_DIR="$STATE_DIR/browser-tools"
KEEP_SNAPSHOTS=20

log() { printf '\033[1;36m[backup]\033[0m %s\n' "$*"; }

mkdir -p "$STATE_DIR" "$MEMORY_SEED"
chmod 700 "$STATE_DIR" "$MEMORY_SEED"

backup_live() {      # backup_live <live-src> <state-relative-dest>
    local src="$1" dest="$STATE_DIR/$2"
    [ -e "$src" ] || return 0
    mkdir -p "$(dirname "$dest")"
    rm -rf "$dest"
    cp -a "$src" "$dest"
}

# ---------------------------------------------------------------------------
# Claude memory
# ---------------------------------------------------------------------------
if [ -n "$(ls -A "$MEMORY_DIR" 2>/dev/null)" ]; then
    cp -a "$MEMORY_DIR"/. "$MEMORY_SEED"/
    log "memory-seed: $(find "$MEMORY_SEED" -maxdepth 1 -type f | wc -l) files"
fi

# ---------------------------------------------------------------------------
# Dotfiles / editor config / MCP
# ---------------------------------------------------------------------------
backup_live /config/.gitconfig                      gitconfig
backup_live /config/.config/code-server/config.yaml code-server-config.yaml
backup_live /config/data/User/settings.json         User/settings.json
backup_live /config/data/User/snippets              User/snippets
backup_live /config/.bash_history                   bash_history
backup_live /config/.claude.json                    claude.json
backup_live /config/.npmrc                          npmrc
backup_live /config/workspace/.mcp.json             mcp.json
log "state/: dotfiles refreshed"

# ---------------------------------------------------------------------------
# Secrets (prod log sync creds, HubSpot CLI personal access key)
# ---------------------------------------------------------------------------
backup_live /config/secrets          secrets/config-secrets
backup_live /config/.hscli/config.yml secrets/hscli-config.yml
if [ -d "$STATE_DIR/secrets" ]; then
    chmod -R go-rwx "$STATE_DIR/secrets"
    log "state/secrets: refreshed"
fi

# ---------------------------------------------------------------------------
# browser-tools snapshot
# ---------------------------------------------------------------------------
# browser-tools/ is not a git repo and holds hundreds of hand-written probes.
# Snapshot the scripts and .env (not shots/, node_modules/ or loose images).
# Skips when nothing changed since the last snapshot. If the file count drops
# by more than 10% it still snapshots but does NOT prune, so an overwrite with
# an older copy cannot rotate the good snapshots away.
if [ -d "$BROWSER_TOOLS" ]; then
    mkdir -p "$SNAP_DIR"
    chmod 700 "$SNAP_DIR"
    list_files() {
        ( cd "$BROWSER_TOOLS" && find . \
            \( -path ./shots -o -path ./node_modules \) -prune -o \
            -type f ! -iname '*.png' ! -iname '*.jpg' ! -iname '*.jpeg' \
            -printf '%P\t%s\t%T@\n' | LC_ALL=C sort )
    }
    manifest="$(list_files)"
    sum="$(printf '%s' "$manifest" | sha256sum | cut -c1-16)"
    count="$(printf '%s\n' "$manifest" | grep -c . || true)"
    latest="$(ls -1 "$SNAP_DIR"/browser-tools-*.tar.gz 2>/dev/null | tail -1 || true)"
    if [ -n "$latest" ] && [ -f "$latest.sum" ] && [ "$(cat "$latest.sum")" = "$sum" ]; then
        log "browser-tools: unchanged since $(basename "$latest") ($count files)"
    else
        snap="$SNAP_DIR/browser-tools-$(date +%Y%m%d-%H%M%S).tar.gz"
        printf '%s\n' "$manifest" | cut -f1 \
            | tar czf "$snap" -C "$BROWSER_TOOLS" --no-recursion -T -
        printf '%s' "$sum" > "$snap.sum"
        printf '%s' "$count" > "$snap.count"
        log "browser-tools: snapshot $(basename "$snap") ($count files, $(du -h "$snap" | cut -f1))"

        prev_count=0
        [ -n "$latest" ] && [ -f "$latest.count" ] && prev_count="$(cat "$latest.count")"
        if [ "$prev_count" -gt 0 ] && [ "$count" -lt $(( prev_count * 9 / 10 )) ]; then
            log "WARNING: browser-tools shrank from $prev_count to $count files — not pruning old snapshots."
            log "         Restore: tar xzf $latest -C $BROWSER_TOOLS"
        else
            ls -1 "$SNAP_DIR"/browser-tools-*.tar.gz | head -n -"$KEEP_SNAPSHOTS" \
                | while read -r old; do rm -f "$old" "$old.sum" "$old.count"; done
        fi
    fi
fi

# ---------------------------------------------------------------------------
# Keep secrets in the web-served workspace unreadable by www-data
# ---------------------------------------------------------------------------
for f in /config/workspace/.mcp.json "$BROWSER_TOOLS/.env" "$BROWSER_TOOLS"/.auth/*; do
    [ -f "$f" ] && chmod 600 "$f"
done
# Last, because cp -a above copies the live memory dir's 0755 onto memory-seed/.
for d in "$STATE_DIR" "$MEMORY_SEED" "$BROWSER_TOOLS/.auth" /config/workspace/.claude; do
    [ -d "$d" ] && chmod 700 "$d"
done
# Not secret, but never meant to be public (ruling 2026-11-09): block www-data.
[ -d /config/workspace/projects ] && chmod 750 /config/workspace/projects
true
