#!/usr/bin/env bash
# =============================================================================
# GIGARep Mac Mini Provisioning Script v3
# =============================================================================
# Usage: sudo bash gigarep-provision-v3.sh <hostname>
# Example: sudo bash gigarep-provision-v3.sh gigarep-41
#
# Replaces v2 — written after gigarep-40 test run revealed critical failures.
# Key lessons hardcoded: no brew for node, no brew as root, Node 22 .pkg,
# binary downloads for himalaya/jq, DMG for BlueBubbles, npm for gog/openclaw.
#
# Runtime: ~8–10 min on Intel i3 Ventura 13.4 (fresh machine)
# Idempotent: safe to re-run at any stage
# =============================================================================

set -uo pipefail
# NOTE: NOT using set -e — non-critical failures (gog, jq, etc.) should not abort the script

# ─── CONSTANTS ────────────────────────────────────────────────────────────────
SCRIPT_VERSION="3.0.0"
SCRIPT_DATE="2026-03-23"

# Fleet-wide credentials
TAILSCALE_AUTH_KEY="tskey-auth-kwmZ5Rbtp711CNTRL-vEUExpEv5xDLywoVerYFxDMyXUtRyN9H"
REALVNC_ACCESS_KEY="wN9ug8gYw3nDHW9Ufx8k"
REALVNC_ACCESS_KEY_ID="mprATAMb7dZejSSvYdQ"
SUPABASE_URL="https://sfykavjsaywsrezsvtqs.supabase.co"
SUPABASE_ANON_KEY="sb_publishable_y3BwL7hcliCenjZ9Cp4cbA_LLDbuQgV"
VNC_PASSWORD="GIGARep2026!"

# Download URLs — pinned versions, no latest redirects
NODE22_PKG_URL="https://nodejs.org/dist/v22.14.0/node-v22.14.0.pkg"
HIMALAYA_URL="https://github.com/pimalaya/himalaya/releases/download/v1.2.0/himalaya.x86_64-darwin.tgz"
JQ_URL="https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-amd64"
BLUEBUBBLES_DMG_URL="https://github.com/BlueBubblesApp/bluebubbles-server/releases/download/v1.9.9/BlueBubbles-1.9.9.dmg"

# Paths
LOG_FILE="/var/log/gigarep-provision.log"
GIGAREP_SECRETS_DIR="/etc/gigarep"
LAUNCHDAEMON_PLIST="/Library/LaunchDaemons/com.gigarep.openclaw.plist"
TMP_DIR="/tmp/gigarep-provision-$$"

# ─── ARGUMENT VALIDATION ──────────────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
    echo "ERROR: This script must be run as root (sudo bash $0 <hostname>)" >&2
    exit 1
fi

if [[ $# -lt 1 ]]; then
    echo "ERROR: Hostname argument required" >&2
    echo "Usage: sudo bash $0 gigarep-41" >&2
    exit 1
fi

TARGET_HOSTNAME="$1"

# ─── DETECT ADMIN USER ────────────────────────────────────────────────────────
# $SUDO_USER is set by sudo to the original invoking user
if [[ -n "${SUDO_USER:-}" ]]; then
    ADMIN_USER="$SUDO_USER"
else
    # Fallback: find first non-root admin account
    ADMIN_USER=$(dscl . -list /Users UniqueID | awk '$2 >= 501 && $2 < 1000 {print $1}' | grep -v '_' | head -1)
    if [[ -z "$ADMIN_USER" ]]; then
        echo "ERROR: Could not detect admin user. Run with sudo from admin account." >&2
        exit 1
    fi
fi

ADMIN_HOME=$(eval echo "~$ADMIN_USER")
BREW_PREFIX=$(sudo -u "$ADMIN_USER" brew --prefix 2>/dev/null || echo "/usr/local")

echo "Detected admin user: $ADMIN_USER (home: $ADMIN_HOME)"
echo "Brew prefix: $BREW_PREFIX"

# ─── LOGGING SETUP ────────────────────────────────────────────────────────────
mkdir -p "$(dirname "$LOG_FILE")"
exec > >(tee -a "$LOG_FILE") 2>&1

log() {
    echo "[$(date '+%m/%d %H:%M')] $*"
}

log_section() {
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo "  $*"
    echo "════════════════════════════════════════════════════════════════"
}

log "GIGARep Provisioning v${SCRIPT_VERSION} (${SCRIPT_DATE})"
log "Target hostname: $TARGET_HOSTNAME"
log "Admin user: $ADMIN_USER"
log "Log: $LOG_FILE"

# ─── SUDO KEEPALIVE ──────────────────────────────────────────────────────────
# Refresh sudo timestamp every 60s so we never time out mid-install
sudo -v
(
    while true; do
        sleep 60
        sudo -v
    done
) &
SUDO_KEEPALIVE_PID=$!
trap 'kill $SUDO_KEEPALIVE_PID 2>/dev/null; rm -rf "$TMP_DIR"' EXIT

# ─── TEMP DIRECTORY ───────────────────────────────────────────────────────────
mkdir -p "$TMP_DIR"

# ─── HELPER FUNCTIONS ─────────────────────────────────────────────────────────

# Run command as admin user (not root)
as_admin() {
    sudo -u "$ADMIN_USER" "$@"
}

# Run command as admin user with HOME set correctly
as_admin_env() {
    sudo -u "$ADMIN_USER" HOME="$ADMIN_HOME" "$@"
}

# Check if app is installed
app_installed() {
    [[ -d "/Applications/$1" ]] || [[ -d "$ADMIN_HOME/Applications/$1" ]]
}

# Check if command exists
cmd_exists() {
    command -v "$1" &>/dev/null
}

# Download with curl, retry 3x, progress suppressed
download() {
    local url="$1"
    local dest="$2"
    curl -fsSL --retry 3 --retry-delay 5 -o "$dest" "$url"
}

# ─── VERIFICATION TRACKING ────────────────────────────────────────────────────
VERIFY_PASS=0
VERIFY_FAIL=0
VERIFY_LOG=()

verify_check() {
    local label="$1"
    local result="$2"   # "pass" or "fail"
    local detail="${3:-}"

    if [[ "$result" == "pass" ]]; then
        VERIFY_PASS=$((VERIFY_PASS + 1))
        VERIFY_LOG+=("  ✅ $label${detail:+  ($detail)}")
    else
        VERIFY_FAIL=$((VERIFY_FAIL + 1))
        VERIFY_LOG+=("  ❌ $label${detail:+  ($detail)}")
    fi
}

# =============================================================================
# PHASE 1 — SYSTEM CONFIGURATION
# =============================================================================
log_section "PHASE 1 — System Configuration"

# Set hostname
log "Setting hostname to: $TARGET_HOSTNAME"
scutil --set ComputerName  "$TARGET_HOSTNAME"
scutil --set LocalHostName "$TARGET_HOSTNAME"
scutil --set HostName      "$TARGET_HOSTNAME"
log "Hostname set."

# Disable sleep (Mac Mini stays awake)
log "Disabling sleep..."
pmset -a sleep 0 displaysleep 0 disksleep 0 womp 1 autorestart 1 || true

# Enable SSH (Remote Login)
log "Enabling SSH..."
systemsetup -setremotelogin on 2>/dev/null || true

# Inject Mac Studio SSH public key for passwordless remote management
log "Injecting Mac Studio SSH key for remote management..."
MAC_STUDIO_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHXIPMdjiuReXH2DzH059UTWBIiQEiZHfLp/cKW7Xzyu admin@Mac.attlocal.net"
SSH_DIR="$ADMIN_HOME/.ssh"
mkdir -p "$SSH_DIR"
if ! grep -qF "$MAC_STUDIO_PUBKEY" "$SSH_DIR/authorized_keys" 2>/dev/null; then
    echo "$MAC_STUDIO_PUBKEY" >> "$SSH_DIR/authorized_keys"
    log "Mac Studio SSH key added."
else
    log "Mac Studio SSH key already present."
fi
chown -R "$ADMIN_USER:staff" "$SSH_DIR"
chmod 700 "$SSH_DIR"
chmod 600 "$SSH_DIR/authorized_keys"

# Enable automatic restart after power failure
log "Enabling auto-restart after power failure..."
pmset -a autorestart 1 || true

# Set timezone to Eastern
log "Setting timezone to America/New_York..."
systemsetup -settimezone "America/New_York" 2>/dev/null || true

# Enable NTP
systemsetup -setusingnetworktime on 2>/dev/null || true

log "System configuration complete."

# =============================================================================
# PHASE 2 — HOMEBREW (install if missing, update otherwise)
# =============================================================================
log_section "PHASE 2 — Homebrew"

if as_admin_env brew --version &>/dev/null; then
    log "Homebrew already installed. Updating..."
    as_admin_env brew update --quiet || log "WARN: brew update failed (non-fatal)"
else
    log "Installing Homebrew as $ADMIN_USER..."
    as_admin_env bash -c "NONINTERACTIVE=1 /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    # Reload brew prefix after install
    BREW_PREFIX=$(as_admin_env brew --prefix 2>/dev/null || echo "/usr/local")
    log "Homebrew installed at: $BREW_PREFIX"
fi

# Ensure brew is in PATH for subsequent commands
export PATH="$BREW_PREFIX/bin:$PATH"

log "Homebrew ready."

# =============================================================================
# PHASE 3 — NODE 22 via .pkg (NEVER brew install node)
# =============================================================================
log_section "PHASE 3 — Node.js 22 (.pkg)"

# Check if Node 22+ is already installed
CURRENT_NODE_VERSION=""
if cmd_exists node; then
    CURRENT_NODE_VERSION=$(node --version 2>/dev/null | sed 's/v//' | cut -d. -f1)
fi

if [[ -n "$CURRENT_NODE_VERSION" ]] && [[ "$CURRENT_NODE_VERSION" -ge 22 ]]; then
    log "Node.js $(node --version) already installed — skipping."
else
    log "Downloading Node.js 22 .pkg from nodejs.org..."
    download "$NODE22_PKG_URL" "$TMP_DIR/node22.pkg"
    log "Installing Node.js 22 .pkg..."
    installer -pkg "$TMP_DIR/node22.pkg" -target / -verboseR
    log "Node.js 22 installed."
    # Update PATH to pick up node immediately
    export PATH="/usr/local/bin:$PATH"
fi

NODE_VERSION=$(node --version 2>/dev/null || echo "NOT FOUND")
NPM_VERSION=$(npm --version 2>/dev/null || echo "NOT FOUND")
log "Node: $NODE_VERSION | npm: $NPM_VERSION"

# =============================================================================
# PHASE 4 — npm SSL Fix (MUST happen before ANY npm command)
# =============================================================================
log_section "PHASE 4 — npm SSL Fix"

# Apply globally (system npmrc) and for admin user
# Fresh Ventura has cert chain issues with npm — this must be set before install

NPM_SYSTEM_RC="/etc/npmrc"
NPM_USER_RC="$ADMIN_HOME/.npmrc"

log "Writing npm SSL config to $NPM_SYSTEM_RC..."
cat > "$NPM_SYSTEM_RC" <<'EOF'
strict-ssl=false
cafile=/etc/ssl/cert.pem
EOF

log "Writing npm SSL config to $NPM_USER_RC..."
cat > "$NPM_USER_RC" <<'EOF'
strict-ssl=false
cafile=/etc/ssl/cert.pem
EOF
chown "$ADMIN_USER:staff" "$NPM_USER_RC"

# Also configure via npm config set for the admin user
as_admin_env npm config set strict-ssl false 2>/dev/null || true
as_admin_env npm config set cafile /etc/ssl/cert.pem 2>/dev/null || true

log "npm SSL fix applied."

# =============================================================================
# PHASE 5 — OpenClaw via npm
# =============================================================================
log_section "PHASE 5 — OpenClaw"

if cmd_exists openclaw; then
    INSTALLED_OC_VERSION=$(openclaw --version 2>/dev/null || echo "unknown")
    log "OpenClaw already installed ($INSTALLED_OC_VERSION). Checking for updates..."
    npm install -g openclaw --quiet 2>&1 | tail -5 || log "WARN: openclaw update failed (non-fatal)"
else
    log "Installing OpenClaw via npm..."
    npm install -g openclaw 2>&1 | tail -20
    log "OpenClaw installed."
fi

# Verify
if cmd_exists openclaw; then
    log "OpenClaw version: $(openclaw --version 2>/dev/null || echo 'installed')"
else
    log "ERROR: openclaw not found in PATH after install!"
fi

# =============================================================================
# PHASE 5b — Claude Code via npm
# =============================================================================
log_section "PHASE 5b — Claude Code"

if cmd_exists claude; then
    INSTALLED_CC_VERSION=$(claude --version 2>/dev/null || echo "unknown")
    log "Claude Code already installed ($INSTALLED_CC_VERSION). Checking for updates..."
    npm install -g @anthropic-ai/claude-code --quiet 2>&1 | tail -5 || log "WARN: claude-code update failed (non-fatal)"
else
    log "Installing Claude Code via npm..."
    npm install -g @anthropic-ai/claude-code 2>&1 | tail -20
    log "Claude Code installed."
fi

# Verify
if cmd_exists claude; then
    log "Claude Code version: $(claude --version 2>/dev/null || echo 'installed')"
else
    log "WARN: claude not found in PATH after install — may need PATH update (non-fatal)"
fi

# Write Claude Code settings for max power defaults
CLAUDE_CONFIG_DIR="$ADMIN_HOME/.claude"
mkdir -p "$CLAUDE_CONFIG_DIR"
cat > "$CLAUDE_CONFIG_DIR/settings.json" <<'CCEOF'
{
  "model": "claude-opus-4-6",
  "permissions": {
    "allow": ["Bash(*)", "Computer(*)", "Edit(*)", "Read(*)", "Write(*)", "WebFetch(*)", "WebSearch(*)"]
  },
  "preferences": {
    "thinking": "max",
    "verbose": false
  }
}
CCEOF

# Set API key so Claude Code doesn't ask for OAuth
cat > "$CLAUDE_CONFIG_DIR/.env" <<'CCENV'
ANTHROPIC_API_KEY=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
CCENV

# Also add to shell profile for CLI usage
echo 'export ANTHROPIC_API_KEY="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"' >> "$ADMIN_HOME/.zshrc"

chown -R "$ADMIN_USER:staff" "$CLAUDE_CONFIG_DIR"
log "Claude Code settings + API key written (Opus 4.6, max thinking, full permissions)."

# =============================================================================
# PHASE 6 — Email Tools (himalaya binary, gog npm, jq binary)
# =============================================================================
log_section "PHASE 6 — Email Tools"

# ── 6a. himalaya — direct binary (brew fails on Ventura i3) ──────────────────
log "Installing himalaya..."
if [[ -f "/usr/local/bin/himalaya" ]]; then
    log "himalaya already installed — skipping."
else
    download "$HIMALAYA_URL" "$TMP_DIR/himalaya.tgz"
    tar -xzf "$TMP_DIR/himalaya.tgz" -C "$TMP_DIR"
    install -m 755 "$TMP_DIR/himalaya" /usr/local/bin/himalaya
    log "himalaya installed: $(himalaya --version 2>/dev/null || echo 'ok')"
fi

# ── 6b. gog — npm install (not in brew) ───────────────────────────────────────
log "Installing gog..."
if cmd_exists gog; then
    log "gog already installed — skipping."
else
    npm install -g gog 2>&1 | tail -10 || {
        log "WARN: gog npm install failed — non-fatal, continuing"
    }
    log "gog status: $(gog --version 2>/dev/null || echo 'not found — install manually later')"
fi

# ── 6c. jq — direct binary (brew fails as root on Ventura) ───────────────────
log "Installing jq..."
if [[ -f "/usr/local/bin/jq" ]]; then
    log "jq already installed — skipping."
else
    download "$JQ_URL" "$TMP_DIR/jq"
    install -m 755 "$TMP_DIR/jq" /usr/local/bin/jq
    log "jq installed: $(jq --version 2>/dev/null || echo 'ok')"
fi

# =============================================================================
# PHASE 7 — Tailscale (brew cask, run as admin user)
# =============================================================================
log_section "PHASE 7 — Tailscale"

if app_installed "Tailscale.app"; then
    log "Tailscale already installed — skipping install."
else
    log "Installing Tailscale via brew cask (as $ADMIN_USER)..."
    as_admin_env brew install --cask tailscale --quiet 2>&1 | tail -20
    log "Tailscale installed."
fi

# Authenticate Tailscale
log "Authenticating Tailscale..."
TAILSCALE_BIN="/Applications/Tailscale.app/Contents/MacOS/Tailscale"

if [[ -f "$TAILSCALE_BIN" ]]; then
    # Start tailscaled if not running
    if ! pgrep -x tailscaled &>/dev/null; then
        log "Starting tailscaled..."
        # Launch via open or launchctl
        open -a Tailscale 2>/dev/null || true
        sleep 5
    fi

    CURRENT_TS_STATUS=$("$TAILSCALE_BIN" status 2>/dev/null | head -1 || echo "not connected")
    CURRENT_TS_IP=$("$TAILSCALE_BIN" ip -4 2>/dev/null || echo "")
    if [[ -n "$CURRENT_TS_IP" ]] && ! echo "$CURRENT_TS_STATUS" | grep -q "^#"; then
        log "Tailscale already connected ($CURRENT_TS_IP). Skipping re-auth to avoid duplicate entries."
    elif echo "$CURRENT_TS_STATUS" | grep -q "^#"; then
        log "Tailscale not authenticated. Connecting..."
        "$TAILSCALE_BIN" up \
            --authkey "$TAILSCALE_AUTH_KEY" \
            --hostname "$TARGET_HOSTNAME" \
            --accept-routes \
            --accept-dns \
            2>&1 || log "WARN: Tailscale up returned non-zero (may need ACL tags to be configured)"
    else
        log "Tailscale already connected."
    fi
else
    log "WARN: Tailscale binary not found at $TAILSCALE_BIN — checking alternate paths..."
    # Fallback: try CLI path
    if cmd_exists tailscale; then
        tailscale up --authkey "$TAILSCALE_AUTH_KEY" --hostname "$TARGET_HOSTNAME" 2>&1 || \
            log "WARN: tailscale up returned non-zero"
    else
        log "WARN: Tailscale not found — skipping auth"
    fi
fi

# =============================================================================
# PHASE 8 — BlueBubbles (direct DMG — brew cask fails)
# =============================================================================
log_section "PHASE 8 — BlueBubbles"

if app_installed "BlueBubbles.app"; then
    log "BlueBubbles already installed — skipping."
else
    log "Downloading BlueBubbles DMG..."
    download "$BLUEBUBBLES_DMG_URL" "$TMP_DIR/BlueBubbles.dmg"

    log "Mounting DMG..."
    MOUNT_POINT=$(hdiutil attach "$TMP_DIR/BlueBubbles.dmg" -nobrowse -quiet -mountrandom /tmp | tail -1 | awk '{print $NF}')

    log "Copying BlueBubbles.app to /Applications..."
    cp -R "$MOUNT_POINT/BlueBubbles.app" /Applications/

    log "Unmounting DMG..."
    hdiutil detach "$MOUNT_POINT" -quiet

    # Fix permissions
    chown -R "$ADMIN_USER:staff" /Applications/BlueBubbles.app
    log "BlueBubbles installed."
fi

# =============================================================================
# PHASE 9 — RealVNC (brew cask + license)
# =============================================================================
log_section "PHASE 9 — RealVNC"

# ── 9a. Install RealVNC Server via brew cask (as admin user) ─────────────────
if [[ -d "/Library/vnc" ]] || app_installed "VNC Server.app" || [[ -f "/usr/sbin/vnclicense" ]]; then
    log "RealVNC Server already installed — skipping install."
else
    log "Installing RealVNC Server via brew cask (as $ADMIN_USER)..."
    as_admin_env brew install --cask vnc-server --quiet 2>&1 | tail -20
    log "RealVNC Server installed."
fi

# ── 9b. License RealVNC ───────────────────────────────────────────────────────
log "Applying RealVNC Cloud license..."
VNCSERVER_BIN=""
for candidate in \
    "/Library/vnc/vncserver" \
    "/usr/sbin/vncserver" \
    "$(find /Applications -name vncserver -type f 2>/dev/null | head -1)"; do
    if [[ -f "$candidate" ]]; then
        VNCSERVER_BIN="$candidate"
        break
    fi
done

if [[ -n "$VNCSERVER_BIN" ]]; then
    "$VNCSERVER_BIN" -service -joinCloud "$REALVNC_ACCESS_KEY_ID" "$REALVNC_ACCESS_KEY" 2>&1 || \
        log "WARN: VNC joinCloud returned non-zero (may already be licensed)"
    log "RealVNC license applied."
else
    log "WARN: vncserver binary not found — skipping license step"
fi

# ── 9c. Set VNC password ──────────────────────────────────────────────────────
log "Setting VNC password..."
for vnc_passwd_tool in \
    "/Library/vnc/vncpasswd" \
    "$(find /Applications -name vncpasswd -type f 2>/dev/null | head -1)"; do
    if [[ -f "$vnc_passwd_tool" ]]; then
        echo "$VNC_PASSWORD" | "$vnc_passwd_tool" --password "$VNC_PASSWORD" 2>/dev/null || true
        break
    fi
done

# =============================================================================
# PHASE 9.5 — Google Chrome + Bookmarks
# =============================================================================
log_section "PHASE 9.5 — Google Chrome + Desktop Bookmarks"

# ── 9.5a. Install Google Chrome via DMG ──────────────────────────────────────
CHROME_DMG_URL="https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg"

if app_installed "Google Chrome.app"; then
    log "Google Chrome already installed — skipping."
else
    log "Downloading Google Chrome..."
    if download "$CHROME_DMG_URL" "$TMP_DIR/GoogleChrome.dmg"; then
        log "Mounting Chrome DMG..."
        CHROME_MOUNT=$(hdiutil attach "$TMP_DIR/GoogleChrome.dmg" -nobrowse -quiet -mountrandom /tmp | tail -1 | awk '{print $NF}')
        if [[ -d "$CHROME_MOUNT/Google Chrome.app" ]]; then
            cp -R "$CHROME_MOUNT/Google Chrome.app" /Applications/
            chown -R "$ADMIN_USER:staff" "/Applications/Google Chrome.app"
            log "Google Chrome installed."
        else
            log "WARN: Google Chrome.app not found in DMG — skipping (non-fatal)"
        fi
        hdiutil detach "$CHROME_MOUNT" -quiet 2>/dev/null || true
    else
        log "WARN: Chrome download failed — skipping (non-fatal)"
    fi
fi

# ── 9.5b. Create desktop bookmarks (clickable .webloc files) ─────────────────
log "Creating desktop bookmarks..."
DESKTOP="$ADMIN_HOME/Desktop"

# Monday.com CRM
cat > "$DESKTOP/Monday CRM.webloc" <<WEBLOC
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>URL</key><string>https://monday.com</string></dict>
</plist>
WEBLOC

# toplendingusa.dev (internal web app)
cat > "$DESKTOP/Top Lending USA.webloc" <<WEBLOC
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>URL</key><string>https://toplendingusa.dev</string></dict>
</plist>
WEBLOC

# Gmail (toplendingusa.com workspace)
cat > "$DESKTOP/Gmail.webloc" <<WEBLOC
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>URL</key><string>https://mail.google.com</string></dict>
</plist>
WEBLOC

chown "$ADMIN_USER:staff" "$DESKTOP"/*.webloc 2>/dev/null || true
log "Desktop bookmarks created: Monday CRM, Top Lending USA, Gmail"

# ── 9.5c. Set Chrome as default browser (non-fatal) ─────────────────────────
# This requires the app to have been opened once — skip if it fails
if app_installed "Google Chrome.app"; then
    log "NOTE: Chrome must be opened once to register as default browser handler."
    log "Reps will see a 'set as default?' prompt on first launch."
fi

# =============================================================================
# PHASE 10 — Disable macOS Screen Sharing (conflicts with RealVNC on port 5900)
# =============================================================================
log_section "PHASE 10 — Disable macOS Screen Sharing (RealVNC is primary)"

log "Disabling macOS Screen Sharing to avoid port 5900 conflict with RealVNC..."
# Stop and disable the built-in Screen Sharing / ARD service
/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart \
    -deactivate \
    -configure -access -off \
    2>&1 | tail -5 || log "WARN: kickstart deactivate returned non-zero (non-fatal)"

launchctl unload -w /System/Library/LaunchDaemons/com.apple.screensharing.plist 2>/dev/null || true

log "macOS Screen Sharing disabled — RealVNC Server is the sole remote access method."

# =============================================================================
# PHASE 11 — /etc/gigarep Secrets
# =============================================================================
log_section "PHASE 11 — Secrets"

log "Writing /etc/gigarep secrets..."
mkdir -p "$GIGAREP_SECRETS_DIR"
chmod 700 "$GIGAREP_SECRETS_DIR"

cat > "$GIGAREP_SECRETS_DIR/env" <<EOF
# GIGARep Fleet Secrets — written by provisioning v${SCRIPT_VERSION}
# Generated: $(date '+%Y-%m-%dT%H:%M:%S')
# Machine: $TARGET_HOSTNAME

GIGAREP_HOSTNAME=$TARGET_HOSTNAME
GIGAREP_ADMIN_USER=$ADMIN_USER

TAILSCALE_AUTH_KEY=$TAILSCALE_AUTH_KEY
REALVNC_ACCESS_KEY=$REALVNC_ACCESS_KEY
REALVNC_ACCESS_KEY_ID=$REALVNC_ACCESS_KEY_ID

SUPABASE_URL=$SUPABASE_URL
SUPABASE_ANON_KEY=$SUPABASE_ANON_KEY

VNC_PASSWORD=$VNC_PASSWORD
EOF

chmod 600 "$GIGAREP_SECRETS_DIR/env"
chown root:wheel "$GIGAREP_SECRETS_DIR/env"

log "Secrets written to $GIGAREP_SECRETS_DIR/env"

# Log Supabase registration payload (machines table not yet created)
MACHINE_PAYLOAD=$(cat <<EOF
{
  "hostname": "$TARGET_HOSTNAME",
  "admin_user": "$ADMIN_USER",
  "os_version": "$(sw_vers -productVersion 2>/dev/null || echo unknown)",
  "arch": "$(uname -m)",
  "node_version": "$(node --version 2>/dev/null || echo unknown)",
  "provisioned_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "provision_version": "$SCRIPT_VERSION"
}
EOF
)
log "Supabase registration payload (machines table pending creation):"
log "$MACHINE_PAYLOAD"
echo "$MACHINE_PAYLOAD" > "$GIGAREP_SECRETS_DIR/machine-registration.json"

# =============================================================================
# PHASE 12 — OpenClaw LaunchDaemon
# =============================================================================
log_section "PHASE 12 — OpenClaw LaunchDaemon"

# Find openclaw binary path
OPENCLAW_BIN=$(which openclaw 2>/dev/null || echo "/usr/local/bin/openclaw")
NODE_BIN=$(which node 2>/dev/null || echo "/usr/local/bin/node")

# Create workspace directory structure (deploy-openclaw-config.sh also creates these,
# but having them ready after provisioning means OpenClaw can start cleanly)
WORKSPACE_DIR="$ADMIN_HOME/gigarep"
log "Creating workspace: $WORKSPACE_DIR"
sudo -u "$ADMIN_USER" mkdir -p "$WORKSPACE_DIR"/{logs,memory,tasks,config,tmp,docs}

# Fleet standard label: com.gigarep.openclaw (see CANONICAL-PATHS.md)
log "Writing LaunchDaemon plist: $LAUNCHDAEMON_PLIST"
cat > "$LAUNCHDAEMON_PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.gigarep.openclaw</string>

    <key>ProgramArguments</key>
    <array>
        <string>$OPENCLAW_BIN</string>
        <string>gateway</string>
        <string>start</string>
    </array>

    <key>UserName</key>
    <string>$ADMIN_USER</string>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <true/>

    <key>StandardOutPath</key>
    <string>/var/log/openclaw.log</string>

    <key>StandardErrorPath</key>
    <string>/var/log/openclaw-error.log</string>

    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${BREW_PREFIX}/bin</string>
        <key>HOME</key>
        <string>$ADMIN_HOME</string>
        <key>NODE_EXTRA_CA_CERTS</key>
        <string>/etc/ssl/cert.pem</string>
    </dict>

    <key>ThrottleInterval</key>
    <integer>30</integer>

    <key>WorkingDirectory</key>
    <string>$ADMIN_HOME</string>
</dict>
</plist>
EOF

chown root:wheel "$LAUNCHDAEMON_PLIST"
chmod 644 "$LAUNCHDAEMON_PLIST"

# Load the daemon (unload first if already loaded)
launchctl unload "$LAUNCHDAEMON_PLIST" 2>/dev/null || true
launchctl load -w "$LAUNCHDAEMON_PLIST"
log "LaunchDaemon loaded."

# =============================================================================
# PHASE 12.5 — NATS CLI (client only — server runs on M4 hub)
# =============================================================================
log_section "PHASE 12.5 — NATS CLI"

NATS_CLI_URL="https://github.com/nats-io/natscli/releases/download/v0.1.5/nats-0.1.5-darwin-amd64.zip"
NATS_SERVER_URL="nats://gigarep-m-5:4222"
NATS_TOKEN="gigarep-nats-fleet-2026"

# ── 12.5a. Install NATS CLI binary ──────────────────────────────────────────
log "Installing NATS CLI..."
if cmd_exists nats; then
    log "nats already installed — skipping."
else
    if download "$NATS_CLI_URL" "$TMP_DIR/nats-cli.zip"; then
        unzip -o "$TMP_DIR/nats-cli.zip" -d "$TMP_DIR/nats-cli" >/dev/null 2>&1
        # Binary is inside a versioned subdirectory
        NATS_BIN=$(find "$TMP_DIR/nats-cli" -name "nats" -type f | head -1)
        if [[ -n "$NATS_BIN" ]]; then
            install -m 755 "$NATS_BIN" /usr/local/bin/nats
            log "nats installed: $(nats --version 2>/dev/null || echo 'ok')"
        else
            log "WARN: nats binary not found in archive — skipping (non-fatal)"
        fi
    else
        log "WARN: NATS CLI download failed — skipping (non-fatal)"
    fi
fi

# ── 12.5b. NATS client context ──────────────────────────────────────────────
log "Configuring NATS client context..."
NATS_CTX_DIR="$ADMIN_HOME/.config/nats/context"
mkdir -p "$NATS_CTX_DIR"

cat > "$NATS_CTX_DIR/gigarep.json" <<EOF
{
  "url": "$NATS_SERVER_URL",
  "token": "$NATS_TOKEN",
  "description": "GIGARep fleet NATS"
}
EOF

echo "gigarep" > "$ADMIN_HOME/.config/nats/context.txt"

chown -R "$ADMIN_USER" "$ADMIN_HOME/.config/nats"
log "NATS context 'gigarep' configured (server: $NATS_SERVER_URL)"

# ── 12.5c. Add NATS env vars to /etc/gigarep/env ────────────────────────────
if [[ -f "$GIGAREP_SECRETS_DIR/env" ]]; then
    if ! grep -q "NATS_TOKEN" "$GIGAREP_SECRETS_DIR/env"; then
        cat >> "$GIGAREP_SECRETS_DIR/env" <<EOF

NATS_TOKEN=$NATS_TOKEN
NATS_URL=$NATS_SERVER_URL
EOF
        log "NATS env vars appended to $GIGAREP_SECRETS_DIR/env"
    else
        log "NATS env vars already in $GIGAREP_SECRETS_DIR/env — skipping."
    fi
else
    log "WARN: $GIGAREP_SECRETS_DIR/env not found — NATS env vars not written"
fi

# =============================================================================
# PHASE 13 — 33-POINT VERIFICATION
# =============================================================================
log_section "PHASE 13 — Verification (35 points)"

echo ""
echo "Running verification checks..."
echo ""

# ── System ────────────────────────────────────────────────────────────────────
# 1. Hostname
ACTUAL_HOSTNAME=$(scutil --get HostName 2>/dev/null || echo "")
[[ "$ACTUAL_HOSTNAME" == "$TARGET_HOSTNAME" ]] && \
    verify_check "Hostname" "pass" "$ACTUAL_HOSTNAME" || \
    verify_check "Hostname" "fail" "got '$ACTUAL_HOSTNAME', expected '$TARGET_HOSTNAME'"

# 2. ComputerName
ACTUAL_CN=$(scutil --get ComputerName 2>/dev/null || echo "")
[[ "$ACTUAL_CN" == "$TARGET_HOSTNAME" ]] && \
    verify_check "ComputerName" "pass" "$ACTUAL_CN" || \
    verify_check "ComputerName" "fail" "got '$ACTUAL_CN'"

# 3. SSH enabled
SSH_STATUS=$(systemsetup -getremotelogin 2>/dev/null || echo "")
echo "$SSH_STATUS" | grep -qi "on" && \
    verify_check "SSH (Remote Login)" "pass" || \
    verify_check "SSH (Remote Login)" "fail" "$SSH_STATUS"

# 4. Sleep disabled
SLEEP_VAL=$(pmset -g | awk '/^[ \t]+sleep/ {print $2}' | head -1)
[[ "$SLEEP_VAL" == "0" ]] && \
    verify_check "Sleep disabled" "pass" || \
    verify_check "Sleep disabled" "fail" "sleep=$SLEEP_VAL"

# ── Homebrew ──────────────────────────────────────────────────────────────────
# 5. Homebrew installed
as_admin_env brew --version &>/dev/null && \
    verify_check "Homebrew" "pass" "$(as_admin_env brew --version 2>/dev/null | head -1)" || \
    verify_check "Homebrew" "fail"

# ── Node.js ───────────────────────────────────────────────────────────────────
# 6. Node 22+ installed
if cmd_exists node; then
    NODE_MAJ=$(node --version | sed 's/v//' | cut -d. -f1)
    [[ "$NODE_MAJ" -ge 22 ]] && \
        verify_check "Node.js 22+" "pass" "$(node --version)" || \
        verify_check "Node.js 22+" "fail" "$(node --version) — need v22+"
else
    verify_check "Node.js 22+" "fail" "node not found"
fi

# 7. npm installed
cmd_exists npm && \
    verify_check "npm" "pass" "$(npm --version)" || \
    verify_check "npm" "fail"

# ── npm SSL ───────────────────────────────────────────────────────────────────
# 8. npm strict-ssl false
NPM_SSL=$(as_admin_env npm config get strict-ssl 2>/dev/null || echo "")
[[ "$NPM_SSL" == "false" ]] && \
    verify_check "npm strict-ssl=false" "pass" || \
    verify_check "npm strict-ssl=false" "fail" "got: $NPM_SSL"

# 9. npm cafile set
NPM_CAFILE=$(as_admin_env npm config get cafile 2>/dev/null || echo "")
[[ "$NPM_CAFILE" == "/etc/ssl/cert.pem" ]] && \
    verify_check "npm cafile=/etc/ssl/cert.pem" "pass" || \
    verify_check "npm cafile=/etc/ssl/cert.pem" "fail" "got: $NPM_CAFILE"

# ── OpenClaw ──────────────────────────────────────────────────────────────────
# 10. openclaw binary exists
cmd_exists openclaw && \
    verify_check "OpenClaw binary" "pass" "$(which openclaw)" || \
    verify_check "OpenClaw binary" "fail"

# 11. openclaw version returns
OPENCLAW_VER=$(openclaw --version 2>/dev/null || echo "")
[[ -n "$OPENCLAW_VER" ]] && \
    verify_check "OpenClaw version" "pass" "$OPENCLAW_VER" || \
    verify_check "OpenClaw version" "fail" "version check failed"

# ── Email Tools ───────────────────────────────────────────────────────────────
# 12. himalaya binary
[[ -f "/usr/local/bin/himalaya" ]] && \
    verify_check "himalaya binary" "pass" "$(/usr/local/bin/himalaya --version 2>/dev/null | head -1 || echo 'installed')" || \
    verify_check "himalaya binary" "fail"

# 13. himalaya executable
[[ -x "/usr/local/bin/himalaya" ]] && \
    verify_check "himalaya executable" "pass" || \
    verify_check "himalaya executable" "fail"

# 14. gog installed
cmd_exists gog && \
    verify_check "gog (npm)" "pass" "$(which gog)" || \
    verify_check "gog (npm)" "fail"

# 15. jq binary
[[ -f "/usr/local/bin/jq" ]] && \
    verify_check "jq binary" "pass" "$(/usr/local/bin/jq --version 2>/dev/null || echo 'installed')" || \
    verify_check "jq binary" "fail"

# 16. jq executable
[[ -x "/usr/local/bin/jq" ]] && \
    verify_check "jq executable" "pass" || \
    verify_check "jq executable" "fail"

# ── Tailscale ─────────────────────────────────────────────────────────────────
# 17. Tailscale app installed
app_installed "Tailscale.app" && \
    verify_check "Tailscale.app" "pass" || \
    verify_check "Tailscale.app" "fail"

# 18. Tailscale binary accessible
TS_BIN="/Applications/Tailscale.app/Contents/MacOS/Tailscale"
[[ -f "$TS_BIN" ]] && \
    verify_check "Tailscale binary" "pass" || \
    verify_check "Tailscale binary" "fail" "not found at $TS_BIN"

# 19. Tailscale connected
if [[ -f "$TS_BIN" ]]; then
    TS_STATUS=$("$TS_BIN" status 2>/dev/null | head -1 || echo "offline")
    if ! echo "$TS_STATUS" | grep -q "^#"; then
        verify_check "Tailscale connected" "pass" "$TS_STATUS"
    else
        verify_check "Tailscale connected" "fail" "$TS_STATUS"
    fi
else
    verify_check "Tailscale connected" "fail" "binary missing"
fi

# ── BlueBubbles ───────────────────────────────────────────────────────────────
# 20. BlueBubbles.app installed
app_installed "BlueBubbles.app" && \
    verify_check "BlueBubbles.app" "pass" || \
    verify_check "BlueBubbles.app" "fail"

# ── Google Chrome ─────────────────────────────────────────────────────────────
# 20.5 Google Chrome installed
app_installed "Google Chrome.app" && \
    verify_check "Google Chrome.app" "pass" || \
    verify_check "Google Chrome.app" "fail"

# 20.6 Desktop bookmarks exist
[[ -f "$ADMIN_HOME/Desktop/Monday CRM.webloc" ]] && \
    verify_check "Desktop bookmarks" "pass" || \
    verify_check "Desktop bookmarks" "fail"

# ── RealVNC ───────────────────────────────────────────────────────────────────
# 21. VNC Server app or library
{ [[ -d "/Library/vnc" ]] || app_installed "VNC Server.app"; } && \
    verify_check "RealVNC Server installed" "pass" || \
    verify_check "RealVNC Server installed" "fail"

# 22. vncserver binary
[[ -n "$VNCSERVER_BIN" ]] && [[ -f "$VNCSERVER_BIN" ]] && \
    verify_check "vncserver binary" "pass" "$VNCSERVER_BIN" || \
    verify_check "vncserver binary" "fail" "not found"

# ── Screen Sharing ────────────────────────────────────────────────────────────
# 23. macOS Screen Sharing disabled (RealVNC replaces it — Phase 10)
SCREENSHARE_RUNNING=$(launchctl list 2>/dev/null | grep -c "screensharing" || echo "0")
[[ "$SCREENSHARE_RUNNING" -eq 0 ]] && \
    verify_check "Screen Sharing disabled" "pass" || \
    verify_check "Screen Sharing disabled" "fail" "screensharing still running — port 5900 conflict with RealVNC"

# ── Secrets ───────────────────────────────────────────────────────────────────
# 24. /etc/gigarep dir exists
[[ -d "$GIGAREP_SECRETS_DIR" ]] && \
    verify_check "/etc/gigarep dir" "pass" || \
    verify_check "/etc/gigarep dir" "fail"

# 25. /etc/gigarep/env exists and readable by root
[[ -f "$GIGAREP_SECRETS_DIR/env" ]] && [[ -r "$GIGAREP_SECRETS_DIR/env" ]] && \
    verify_check "/etc/gigarep/env" "pass" || \
    verify_check "/etc/gigarep/env" "fail"

# 26. Secrets contain expected keys
if [[ -f "$GIGAREP_SECRETS_DIR/env" ]]; then
    grep -q "TAILSCALE_AUTH_KEY" "$GIGAREP_SECRETS_DIR/env" && \
    grep -q "SUPABASE_URL" "$GIGAREP_SECRETS_DIR/env" && \
    grep -q "REALVNC_ACCESS_KEY" "$GIGAREP_SECRETS_DIR/env" && \
        verify_check "Secrets content" "pass" "all expected keys present" || \
        verify_check "Secrets content" "fail" "missing expected keys"
else
    verify_check "Secrets content" "fail" "env file missing"
fi

# ── LaunchDaemon ──────────────────────────────────────────────────────────────
# 27. Plist file exists
[[ -f "$LAUNCHDAEMON_PLIST" ]] && \
    verify_check "LaunchDaemon plist" "pass" || \
    verify_check "LaunchDaemon plist" "fail"

# 28. Plist loaded in launchctl
DAEMON_LOADED=$(launchctl list 2>/dev/null | grep -c "com.gigarep.openclaw" || echo "0")
[[ "$DAEMON_LOADED" -gt 0 ]] && \
    verify_check "LaunchDaemon loaded" "pass" || \
    verify_check "LaunchDaemon loaded" "fail" "not in launchctl list"

# 29. LaunchDaemon plist is valid XML
plutil -lint "$LAUNCHDAEMON_PLIST" &>/dev/null && \
    verify_check "LaunchDaemon plist valid" "pass" || \
    verify_check "LaunchDaemon plist valid" "fail" "plutil lint failed"

# ── Admin User & Permissions ──────────────────────────────────────────────────
# 30. Admin user detected
[[ -n "$ADMIN_USER" ]] && [[ "$ADMIN_USER" != "root" ]] && \
    verify_check "Admin user detected" "pass" "$ADMIN_USER" || \
    verify_check "Admin user detected" "fail" "got: $ADMIN_USER"

# 31. Admin home exists
[[ -d "$ADMIN_HOME" ]] && \
    verify_check "Admin home exists" "pass" "$ADMIN_HOME" || \
    verify_check "Admin home exists" "fail" "$ADMIN_HOME not found"

# 32. /usr/local/bin in PATH
echo "$PATH" | grep -q "/usr/local/bin" && \
    verify_check "/usr/local/bin in PATH" "pass" || \
    verify_check "/usr/local/bin in PATH" "fail"

# ── NATS CLI ─────────────────────────────────────────────────────────────────
# 33. NATS CLI binary
cmd_exists nats && \
    verify_check "NATS CLI binary" "pass" "$(nats --version 2>/dev/null || echo '/usr/local/bin/nats')" || \
    verify_check "NATS CLI binary" "fail" "nats not found in PATH"

# ── Print Verification Report ─────────────────────────────────────────────────
echo ""
echo "════════════════════════════════════════════════════════════════"
echo "  VERIFICATION REPORT — $TARGET_HOSTNAME"
echo "════════════════════════════════════════════════════════════════"
for line in "${VERIFY_LOG[@]}"; do
    echo "$line"
done
echo ""
echo "  Result: $VERIFY_PASS / $((VERIFY_PASS + VERIFY_FAIL)) checks passed"
echo "════════════════════════════════════════════════════════════════"
echo ""

# =============================================================================
# Mosyle MDM Enrollment
# =============================================================================
log_section "Mosyle MDM Enrollment"
if profiles status -type enrollment 2>/dev/null | grep -q "MDM enrollment: Yes"; then
    log "Mosyle MDM already enrolled. Skipping."
else
    log "Opening Mosyle enrollment page..."
    as_admin open 'https://join.mosyle.com/?account=gigagoods' 2>/dev/null || true
    log "Mosyle enrollment page opened — click through to install the MDM profile."
fi

# =============================================================================
# DONE
# =============================================================================
log_section "PROVISIONING COMPLETE"

TOTAL_CHECKS=$((VERIFY_PASS + VERIFY_FAIL))
log "Hostname:     $TARGET_HOSTNAME"
log "Admin user:   $ADMIN_USER"
log "Node:         $(node --version 2>/dev/null || echo N/A)"
log "OpenClaw:     $(openclaw --version 2>/dev/null || echo N/A)"
log "Verification: $VERIFY_PASS/$TOTAL_CHECKS passed"
log "Log file:     $LOG_FILE"
log "Provision v:  $SCRIPT_VERSION"

if [[ "$VERIFY_FAIL" -gt 0 ]]; then
    log ""
    log "⚠️  $VERIFY_FAIL check(s) FAILED. Review the report above and fix before deployment."
    exit 2
else
    log ""
    log "✅  All $VERIFY_PASS checks passed. Machine $TARGET_HOSTNAME is ready."
    exit 0
fi
