#!/usr/bin/env bash
# Point-in-time state dump for the active dev session. Reads:
#   - Watch App Group container (decoded ComplicationSnapshot,
#     ReloadAudit, per-instance tapestry history)
#   - iOS DEBUG mirrors written by accountStore.ts and netlog.ts under
#     Paths.document/devnet/
#   - Recent CoreSimulator crash reports (so a mid-session native crash
#     surfaces alongside the unified log)
#
# Writes a timestamped subdir under the most-recent session directory
# (`temp/dev-logs/latest -> 20YYMMDD-HHMMSS/`).

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
source "$SCRIPT_DIR/sim.env"

cd "$REPO_ROOT"

SESSION="${1:-temp/dev-logs/latest}"
if [[ ! -e "$SESSION" ]]; then
  echo "No session at $SESSION. Run scripts/dev/tail-logs.sh first."
  exit 1
fi
SESSION_REAL="$(cd "$SESSION" && pwd -P)"
TS="$(date +%Y%m%d-%H%M%S)"
OUT="$SESSION_REAL/snapshot-$TS"
mkdir -p "$OUT/appgroup" "$OUT/responses" "$OUT/crash"

note() { echo "[snapshot] $*"; }

# ---- 1. Watch App Group container ----
# `simctl get_app_container ... groups` prints `groupId<TAB>path`; the path is
# the second column. Pull it out via awk so we don't pass the whole line to
# the directory test.
APP_GROUP_DIR=$(xcrun simctl get_app_container "$WATCH_UDID" "$WATCH_BUNDLE_ID" groups 2>/dev/null | awk -F'\t' '{print $NF}' | head -1 || true)
if [[ -n "$APP_GROUP_DIR" && -d "$APP_GROUP_DIR" ]]; then
  note "Watch App Group: $APP_GROUP_DIR"
  PLIST="$APP_GROUP_DIR/Library/Preferences/group.ht.halflig.app.plist"
  if [[ -f "$PLIST" ]]; then
    cp "$PLIST" "$OUT/appgroup/raw.plist"
    # Decode the well-known keys into readable JSON using `plutil` +
    # the encoded JSON-blob extraction. The snapshot/audit/history
    # values are Data blobs containing JSON written by JSONEncoder, so
    # we read the plist into XML form, pull out the base64 blobs, and
    # decode each.
    plutil -convert xml1 -o "$OUT/appgroup/raw.plist.xml" "$PLIST"

    extract_blob() {
      local key="$1"
      local out="$2"
      # plutil's xml1 form puts each key/value pair as <key>K</key>
      # followed by the value element. Pull the <data> following our
      # key and base64-decode it. `awk` keeps state across lines.
      local b64
      b64=$(awk -v k="$key" '
        $0 ~ "<key>"k"</key>" { found=1; next }
        found && /<data>/      { sub(/.*<data>/, ""); buf = $0; in_data=1; next }
        in_data && /<\/data>/  { sub(/<\/data>.*/, "", $0); buf = buf $0; print buf; exit }
        in_data                { buf = buf $0 }
      ' "$OUT/appgroup/raw.plist.xml" | tr -d ' \n\t')
      if [[ -n "$b64" ]]; then
        echo "$b64" | base64 -D 2>/dev/null | python3 -m json.tool > "$out" 2>/dev/null || {
          # Fallback: write raw if JSON parse fails (still useful).
          echo "$b64" | base64 -D > "${out%.json}.bin" 2>/dev/null || true
        }
      fi
    }

    extract_blob 'tapestry.complication.snapshot.v2' "$OUT/appgroup/snapshot.json"
    extract_blob 'tapestry.complication.audit.v1'    "$OUT/appgroup/audit.json"

    # Per-instance tapestry history — variable key suffix. Walk the
    # plist for any `tapestry.history.v1.<host>` keys.
    grep -oE '<key>tapestry\.history\.v1\.[^<]+</key>' "$OUT/appgroup/raw.plist.xml" \
      | sed -E 's|^<key>(.*)</key>$|\1|' \
      | sort -u \
      | while read -r history_key; do
          host="${history_key#tapestry.history.v1.}"
          extract_blob "$history_key" "$OUT/appgroup/history-$host.json"
        done
  else
    note "App Group plist not found at $PLIST (watch may have never written)."
  fi
else
  note "No Watch App Group container — has the watch app been launched yet?"
fi

# ---- 2. iOS DEBUG mirrors (accounts.json + devnet/responses) ----
IOS_DOCS=$(xcrun simctl get_app_container "$IPHONE_UDID" "$IOS_BUNDLE_ID" data 2>/dev/null | head -1 || true)
if [[ -n "$IOS_DOCS" && -d "$IOS_DOCS/Documents/devnet" ]]; then
  note "iOS devnet mirror: $IOS_DOCS/Documents/devnet"
  if [[ -f "$IOS_DOCS/Documents/devnet/accounts.json" ]]; then
    cp "$IOS_DOCS/Documents/devnet/accounts.json" "$OUT/ios-accounts.json"
  fi
  if [[ -d "$IOS_DOCS/Documents/devnet/responses" ]]; then
    rsync -a --delete "$IOS_DOCS/Documents/devnet/responses/" "$OUT/responses/"
  fi
else
  note "No iOS devnet mirror yet — has the iPhone app been launched? AccountStore writes after first registry mutation."
fi

# ---- 3. Recent crash reports (per foundation doc §3.2.9) ----
CRASH_DIR_GLOBAL="$HOME/Library/Logs/DiagnosticReports"
CRASH_DIR_SIM_IPHONE="$HOME/Library/Logs/CoreSimulator/$IPHONE_UDID"
CRASH_DIR_SIM_WATCH="$HOME/Library/Logs/CoreSimulator/$WATCH_UDID"
for d in "$CRASH_DIR_GLOBAL" "$CRASH_DIR_SIM_IPHONE" "$CRASH_DIR_SIM_WATCH"; do
  if [[ -d "$d" ]]; then
    # Grab the 3 most-recent files (any extension; .ips, .crash, .log).
    ls -t "$d" 2>/dev/null | head -3 | while read -r f; do
      cp -p "$d/$f" "$OUT/crash/$(basename "$d")_$f" 2>/dev/null || true
    done
  fi
done

note "Snapshot written: $OUT"
ls -1 "$OUT"
