#!/usr/bin/env bash
# post-create.sh — first-run provisioning for the Example Dev Box.
#
# Runs once, as the `vscode` user, after the container is created and the repo is
# mounted at /workspace (devcontainer.json: postCreateCommand). This is where
# ADR 0031 §3's "fold setup-builder.sh into the container's first-run step"
# actually happens:
#
#   1. scripts/setup-builder.sh --no-auth --skip-keys
#        → verifies the toolchain, runs `npm ci`, seeds .env.local from the
#          (secret-free) example. The --no-auth flag skips the interactive
#          GitHub Device Flow, which can't run in a non-interactive postCreate —
#          the builder authenticates on first attach instead (see the banner).
#   2. pip install the pinned art-pipeline deps INTO the venv the image created.
#        → setup-builder.sh doesn't touch Python deps; the container layer owns
#          that, installing from the repo's manifest so it stays reproducible.
#   3. A full-stack verification (sharp loads, art libs import) so a green
#        first-run means the box is genuinely ready, not just "built".
#
# No secrets are written here (ADR 0022): .env.local is copied from the example
# with blank placeholders; the per-builder Gemini key and GDS session arrive at
# runtime via the mounted ~/.config/otb volume and /builder-setup.

set -uo pipefail

cd /workspace 2>/dev/null || cd "$(git rev-parse --show-toplevel 2>/dev/null || echo .)"

bold=$'\033[1m'; green=$'\033[32m'; yellow=$'\033[33m'; dim=$'\033[2m'; reset=$'\033[0m'
say()  { echo "${bold}$*${reset}"; }

say "Example Dev Box — first-run provisioning"
echo

# git trusts the mounted workspace even though its owner differs from the
# container user (avoids "detected dubious ownership" on every git command).
git config --global --add safe.directory /workspace 2>/dev/null || true

# node_modules is a container-isolated named volume (see devcontainer.json). A
# fresh volume mounts root-owned, so hand it to the runtime user before the
# npm ci inside setup-builder.sh tries to populate it.
if [ -d node_modules ]; then
  sudo chown vscode:vscode node_modules 2>/dev/null || true
fi

# --- 1. Bring up the firewall BEFORE installing dependencies ------------------
# postStartCommand also runs the firewall on every start, but that's AFTER this
# postCreate step — which would leave `npm ci` + `pip install` below running with
# unrestricted egress on first create, a window a malicious (post)install script
# could exfiltrate through. Apply default-deny up front so dependency installs
# happen behind the allow-list (npm + PyPI + GitHub are allow-listed, so they
# still work). Non-fatal: if it can't apply (e.g. a laptop without NET_ADMIN),
# postStart will report it; we don't block provisioning here.
say "1/4  Securing egress (default-deny firewall, before dependency installs)"
if sudo /usr/local/bin/otb-init-firewall.sh; then
  echo "  ${green}ok${reset}  firewall active — installs run behind the allow-list"
else
  echo "  ${yellow}!!${reset} firewall did not apply (see above); dependency installs will run with open egress this once"
fi
echo

# --- 2. Fold in setup-builder.sh (toolchain + npm ci + .env.local) ------------
say "2/4  Toolchain + dependencies (scripts/setup-builder.sh --no-auth)"
if [ -x scripts/setup-builder.sh ]; then
  if bash scripts/setup-builder.sh --no-auth --skip-keys; then
    echo "  ${green}ok${reset}  setup-builder.sh completed"
  else
    echo "  ${yellow}!!${reset} setup-builder.sh reported a problem — review the output above"
  fi
else
  echo "  ${yellow}!!${reset} scripts/setup-builder.sh not found/executable — running npm ci directly"
  npm ci --no-audit --no-fund || echo "  ${yellow}!!${reset} npm ci failed"
fi
echo

# --- 2. Art pipeline Python deps into the venv --------------------------------
# Non-fatal: a box without art deps is still fully usable for game/GDS work.
# Retry a few times — on a macOS Docker Desktop bind mount, VirtioFS can
# transiently return EDEADLK ("Resource deadlock avoided") reading repo files;
# a retry (and a fresh container) usually clears it. The DO box (#598) has no
# bind mount, so this never bites there.
say "3/4  Art-pipeline Python deps (into ${OTB_VENV:-venv})"
if [ -f modules/art-pipeline/pipeline/requirements.txt ]; then
  art_ok=0
  for attempt in 1 2 3; do
    if pip install --no-cache-dir -r modules/art-pipeline/pipeline/requirements.txt; then
      echo "  ${green}ok${reset}  art deps installed"
      art_ok=1
      break
    fi
    echo "  ${dim}--${reset}  attempt ${attempt} failed; retrying…"
  done
  if [ "$art_ok" -eq 0 ]; then
    echo "  ${yellow}!!${reset} pip install failed after retries — the art pipeline won't run until resolved."
    echo "     On a macOS laptop this is usually Docker Desktop's VirtioFS (EDEADLK):"
    echo "     rebuild the container, or switch Docker Desktop → Settings → General →"
    echo "     file sharing to 'gRPC FUSE'. (The box is otherwise ready.)"
  fi
else
  echo "  ${dim}--${reset}  no modules/art-pipeline/pipeline/requirements.txt; skipping"
fi
echo

# --- 3. Full-stack verification -----------------------------------------------
say "4/4  Verifying the box is ready"
# sharp was verified here as "the native image dep". Task 1003207 removed it: its
# only consumers were the game-era snapshot renderers and an art-pipeline test,
# all of which left this core with the game. Nothing native remains to prove.
# The five art libs must import in the venv.
if python3 -c "import PIL, numpy, scipy, sklearn, certifi" >/dev/null 2>&1; then
  echo "  ${green}ok${reset}  art libs import (Pillow, numpy, scipy, scikit-learn, certifi)"
else
  echo "  ${yellow}!!${reset} one or more art libs failed to import"
fi
echo

# --- Claude Code default permission mode (task 1251) --------------------------
# Match the host (infra/box-source-fetch.sh): default this container's interactive
# Claude Code to bypassPermissions so `claude` never stops for a prompt on the
# (isolated, often unattended) dev box. USER-level (~/.claude/settings.json — the
# persisted otb-claude-config volume), NEVER the repo's project .claude/settings.json,
# so laptops / local clones are unaffected; it merges with the project settings
# (which set no defaultMode). Idempotent — only sets the one key, preserving the rest.
say "Defaulting Claude Code to bypassPermissions (box-only ~/.claude/settings.json)"
if mkdir -p "$HOME/.claude" 2>/dev/null && node -e '
  const fs = require("fs"), p = process.argv[1];
  let s = {}; try { s = JSON.parse(fs.readFileSync(p, "utf8")) || {}; } catch (e) {}
  if (typeof s !== "object" || s === null || Array.isArray(s)) s = {};
  s.permissions = (s.permissions && typeof s.permissions === "object") ? s.permissions : {};
  s.permissions.defaultMode = "bypassPermissions";
  fs.writeFileSync(p, JSON.stringify(s, null, 2) + "\n");
' "$HOME/.claude/settings.json" 2>/dev/null; then
  echo "  ${green}ok${reset}  defaultMode=bypassPermissions written"
else
  echo "  ${yellow}!!${reset} could not write ~/.claude/settings.json (claude will prompt normally)"
fi
echo

say "${green}Box provisioned.${reset}"
cat <<'BANNER'

  Next, on first connect:
    1. Authenticate the GDS CLI:   node scripts/gds/setup.js   (or /builder-setup)
    2. See what you can claim:      /builder-start

  The pixel-art pipeline needs a Google AI Studio key in ~/.config/otb/env
  (that path is a persisted volume, so it survives box rebuilds). Skip if you
  are not running the art pipeline.

BANNER
