#!/usr/bin/env bash
# One-shot iOS sim relaunch with optional MMKV wipe + deep-link nav.
#
# Replaces the four-command verification ritual from V2 plan §1:
#   xcrun simctl terminate ED66… ht.halflig.app
#   rm /Users/.../AppGroup/.../react-query-cache*
#   xcrun simctl launch ED66… ht.halflig.app
#   xcrun simctl openurl ED66… halflight:///(auth)/tapestry
#
# Sim UDID + bundle id come from sim.env. The AppGroup container is
# resolved via `simctl get_app_container … groups` (one round-trip,
# no find).
#
# Usage:
#   scripts/dev/relaunch-ios.sh                            plain relaunch
#   scripts/dev/relaunch-ios.sh --wipe=rq                  wipe React Query MMKV first
#   scripts/dev/relaunch-ios.sh --wipe=rq,user,app         wipe a comma list
#   scripts/dev/relaunch-ios.sh --wipe=mmkv                wipe every MMKV store
#   scripts/dev/relaunch-ios.sh --nav='/(auth)/tapestry'   openurl after launch
#   scripts/dev/relaunch-ios.sh --wipe=rq --nav='/(auth)/tapestry'
#   scripts/dev/relaunch-ios.sh --no-launch                terminate (+ optional wipe) only
#
# Exit: 0 on success, non-zero on misconfig / sim issue.

set -uo pipefail

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

cd "$REPO_ROOT"

WIPE=""
NAV=""
LAUNCH=1
for arg in "$@"; do
  case "$arg" in
    --wipe=*)      WIPE="${arg#--wipe=}" ;;
    --nav=*)       NAV="${arg#--nav=}" ;;
    --no-launch)   LAUNCH=0 ;;
    -h|--help)
      sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
      exit 0
      ;;
    *)
      echo "Unknown flag: $arg" >&2
      exit 2
      ;;
  esac
done

# ---- Sim UDID resolution -----------------------------------------------------
# Prefer sim.env's pinned UDID, but cross-check that *that* sim is booted.
# A mismatch (someone booted a different iPhone via Simulator.app) is a real
# foot-gun on the dev surface: the rest of the loop (tail-logs, snapshot) is
# wired to sim.env, so silently retargeting here would diverge the verify
# path from the observation path.
if ! xcrun simctl list devices booted 2>/dev/null | grep -q "$IPHONE_UDID"; then
  echo "✘ iPhone sim $IPHONE_UDID is not booted." >&2
  echo "  Run: scripts/dev/start-sim.sh --ios-only" >&2
  exit 1
fi

note() { echo "[relaunch-ios] $*"; }

# ---- Terminate ---------------------------------------------------------------
note "Terminating ${IOS_BUNDLE_ID}…"
xcrun simctl terminate "$IPHONE_UDID" "$IOS_BUNDLE_ID" 2>/dev/null || true

# ---- Wipe --------------------------------------------------------------------
# MMKV stores live in the App Group container (`Containers/Shared/AppGroup/
# <uuid>/`). Each store is two files: `<id>` (the data) and `<id>.crc` (the
# integrity-check file). We use a fixed wipe table keyed off the MMKV ids
# from src/state/storage.ts:
#
#   rq        react-query-cache  (TanStack persister, src/lib/query-persister.ts)
#   user      user               (per-account profile cache)
#   app       app                (server-capability flags + global UI prefs)
#   accounts  accounts           (registry: list + activeId)
#   mmkv      all four above
#
# 'secure' (Keychain) is intentionally not in the table: the sim Keychain
# is opaque on-disk and there's no clean CLI wipe short of `simctl uninstall`
# (which also drops the .app — defeats the "fast relaunch" purpose). Reach
# for `scripts/dev/start-sim.sh --ios-only` (rebuilds + reinstalls = clean
# Keychain) if you need that.

# Resolve the App Group container once. Some sims emit a `groupId<TAB>path`
# row, others emit just the path — handle both.
APP_GROUP_DIR=""
if [[ -n "$WIPE" ]]; then
  APP_GROUP_DIR=$(xcrun simctl get_app_container "$IPHONE_UDID" "$IOS_BUNDLE_ID" groups 2>/dev/null \
    | awk -F'\t' 'NF>1{print $NF; exit} NF==1{print $1; exit}')
  if [[ -z "$APP_GROUP_DIR" || ! -d "$APP_GROUP_DIR" ]]; then
    note "✗ Could not resolve App Group container for $IOS_BUNDLE_ID."
    note "  Has the app ever been launched on this sim? Try: scripts/dev/start-sim.sh --ios-only"
    exit 1
  fi
fi

wipe_store() {
  local id="$1"
  local data="$APP_GROUP_DIR/$id"
  local crc="$APP_GROUP_DIR/$id.crc"
  local found=0
  if [[ -e "$data" ]]; then rm -f "$data"; found=1; fi
  if [[ -e "$crc" ]];  then rm -f "$crc";  found=1; fi
  if [[ "$found" -eq 1 ]]; then
    note "  wiped MMKV: $id"
  else
    note "  (skip — MMKV $id not present)"
  fi
}

if [[ -n "$WIPE" ]]; then
  note "Wiping per --wipe=$WIPE"
  IFS=',' read -r -a wipe_items <<< "$WIPE"
  for item in "${wipe_items[@]}"; do
    case "$item" in
      rq)        wipe_store "react-query-cache" ;;
      user)      wipe_store "user" ;;
      app)       wipe_store "app" ;;
      accounts)  wipe_store "accounts" ;;
      mmkv|all)
        wipe_store "react-query-cache"
        wipe_store "user"
        wipe_store "app"
        wipe_store "accounts"
        ;;
      secure)
        note "  ✗ --wipe=secure isn't supported here — sim Keychain wipe needs"
        note "    a full uninstall+reinstall. Run: scripts/dev/start-sim.sh --ios-only"
        exit 2
        ;;
      *)
        note "  ✗ unknown wipe target: $item (valid: rq, user, app, accounts, mmkv)"
        exit 2
        ;;
    esac
  done
fi

# ---- Launch ------------------------------------------------------------------
if [[ "$LAUNCH" -eq 1 ]]; then
  note "Launching ${IOS_BUNDLE_ID}…"
  xcrun simctl launch "$IPHONE_UDID" "$IOS_BUNDLE_ID" >/dev/null
fi

# ---- Deep-link nav -----------------------------------------------------------
# Halflight ships no expo-dev-client, so `halflight://expo-development-client/…`
# is a no-op. Plain `halflight://<path>` works because the URL scheme is
# registered (src/lib/branding.json). We prepend the scheme if the caller
# passed a bare path.
if [[ -n "$NAV" ]]; then
  case "$NAV" in
    *://*) url="$NAV" ;;
    /*)    url="halflight://$NAV" ;;
    *)     url="halflight:///$NAV" ;;
  esac
  # First-frame race: an immediate `openurl` after `simctl launch` arrives
  # while the JS bundle is still parsing; expo-router's linking subscriber
  # isn't mounted yet and the deep link is dropped on the floor. 500 ms is
  # the smallest delay that survives a cold launch on the iPhone 17 Pro sim
  # (~150 ms bundle parse + ~50 ms Provider mount + RN handler attach).
  sleep 0.5
  note "openurl $url"
  xcrun simctl openurl "$IPHONE_UDID" "$url" >/dev/null
fi

note "✓ Done."
