#!/usr/bin/env bash
# Boot the paired iPhone + Apple Watch sim, build iOS via `xcodebuild`
# (path B from `temp/IOS_SIMULATOR_DEBUG_BUILD.md` — preserves the
# pre-launch log attach window), build the watch via `xcodebuild
# HalflightWatch` (path D), and install both. Does NOT launch the iOS
# app — `tail-logs.sh` owns the launch so log streams attach first and
# catch any startup crash.
#
# Idempotent: re-running is safe.
#
# Flags:
#   --watch-only   skip the iOS leg (use after editing `.env.watch.local`)
#   --ios-only     skip the watch leg

set -euo pipefail

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

WATCH_ONLY=0
IOS_ONLY=0
for arg in "$@"; do
  case "$arg" in
    --watch-only) WATCH_ONLY=1 ;;
    --ios-only) IOS_ONLY=1 ;;
    -h|--help)
      sed -n '2,16p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
      exit 0
      ;;
    *)
      echo "Unknown flag: $arg" >&2
      exit 2
      ;;
  esac
done

cd "$REPO_ROOT"

# Disk-space check from foundation doc §3.2.11.
free_gb=$(df -g / | awk 'NR==2 {print $4}')
if [[ "$free_gb" -lt 10 ]]; then
  echo "⚠ Only ${free_gb}G free on /. Sim builds need ~6G; clear:"
  echo "  rm -rf ios/build \$HOME/Library/Developer/Xcode/DerivedData"
fi

# Validate sim UDIDs are still registered (foundation doc one-time facts
# can drift after Xcode updates).
validate_udid() {
  local udid="$1"
  local label="$2"
  if ! xcrun simctl list devices --json | grep -q "$udid"; then
    echo "✘ $label UDID $udid not found in simctl list."
    echo "  Update scripts/dev/sim.env or re-pair via Xcode → Window → Devices and Simulators."
    exit 1
  fi
}

if [[ $WATCH_ONLY -ne 1 ]]; then
  validate_udid "$IPHONE_UDID" "iPhone"
fi
if [[ $IOS_ONLY -ne 1 ]]; then
  validate_udid "$WATCH_UDID" "Watch"
fi

# Foundation doc §3.2.7: every `simctl boot` MUST be followed by
# `bootstatus -b` before any subsequent install / launch / spawn,
# otherwise the first action silently no-ops.
boot_sim() {
  local udid="$1"
  local label="$2"
  echo "▶ Booting $label ($udid)…"
  xcrun simctl boot "$udid" 2>/dev/null || true   # already-booted is fine
  xcrun simctl bootstatus "$udid" -b
}

if [[ $WATCH_ONLY -ne 1 ]]; then
  boot_sim "$IPHONE_UDID" "iPhone"
  open -a Simulator
fi
if [[ $IOS_ONLY -ne 1 ]]; then
  boot_sim "$WATCH_UDID" "Watch"
fi

# Pipe-free runner: log the build output to a file, dump only the
# `error:` lines (or a tail fallback) when xcodebuild fails. The old
# `xcodebuild … | tail -40` form swallowed the actual error lines
# (they emit hundreds of lines before the `BUILD FAILED` summary) and,
# worse, broke any outer-shell pipefail check by always exiting 0 on
# the `tail` side of the pipe — so wrappers that piped this script
# through `tee | tail` saw exit code 0 even when xcodebuild had failed.
run_xcodebuild() {
  local label="$1" log="$2"
  shift 2
  if ! xcodebuild "$@" > "$log" 2>&1; then
    echo "✘ $label build FAILED"
    local errors
    errors=$(grep -B1 -A2 "error:" "$log" | head -60 || true)
    if [[ -n "$errors" ]]; then
      echo "$errors"
    else
      echo "(no 'error:' lines found; tail of build log:)"
      tail -40 "$log"
    fi
    echo "  Full log: $log"
    exit 1
  fi
  tail -5 "$log"
}

# ---- iOS build (path B) ----
if [[ $WATCH_ONLY -ne 1 ]]; then
  echo "▶ Building $IOS_SCHEME for iPhone sim…"
  run_xcodebuild "$IOS_SCHEME" /tmp/halflight-ios-build.log \
    -workspace "$WORKSPACE" \
    -scheme "$IOS_SCHEME" \
    -configuration Debug \
    -destination "platform=iOS Simulator,id=$IPHONE_UDID" \
    -derivedDataPath ios/build/debug-sim-derived \
    build

  IOS_APP="ios/build/debug-sim-derived/Build/Products/Debug-iphonesimulator/$IOS_SCHEME.app"
  if [[ ! -d "$IOS_APP" ]]; then
    echo "✘ iOS .app not found at $IOS_APP"
    exit 1
  fi

  echo "▶ Installing $IOS_APP on iPhone sim…"
  xcrun simctl install "$IPHONE_UDID" "$IOS_APP"
fi

# ---- Watch build (path D) ----
if [[ $IOS_ONLY -ne 1 ]]; then
  echo "▶ Building $WATCH_SCHEME for Watch sim…"
  run_xcodebuild "$WATCH_SCHEME" /tmp/halflight-watch-build.log \
    -workspace "$WORKSPACE" \
    -scheme "$WATCH_SCHEME" \
    -destination "platform=watchOS Simulator,id=$WATCH_UDID" \
    -derivedDataPath ios/build/debug-watch-derived \
    build

  WATCH_APP=$(/usr/bin/find ios/build/debug-watch-derived/Build/Products/Debug-watchsimulator -maxdepth 1 -name 'HalflightWatch.app' -print -quit)
  if [[ -z "$WATCH_APP" || ! -d "$WATCH_APP" ]]; then
    echo "✘ Watch .app not found under ios/build/debug-watch-derived"
    exit 1
  fi

  echo "▶ Installing $WATCH_APP on Watch sim…"
  xcrun simctl install "$WATCH_UDID" "$WATCH_APP"
  # Boot-launch the watch app so the WCSession activates and the
  # complication's host registers the timeline. Cheap; if it's already
  # running this is a no-op.
  xcrun simctl launch "$WATCH_UDID" "$WATCH_BUNDLE_ID" >/dev/null 2>&1 || true
fi

# Resolve the App Group container path on the watch sim — the snapshot
# script reads from it. Write it to a known location so subsequent
# scripts skip the lookup.
if [[ $IOS_ONLY -ne 1 ]]; then
  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:-}" ]]; then
    echo "▶ Watch App Group: $APP_GROUP_DIR"
  fi
fi

mkdir -p temp/dev-logs
cat > temp/dev-logs/.sim-udids <<EOF
IPHONE_UDID=$IPHONE_UDID
WATCH_UDID=$WATCH_UDID
IOS_BUNDLE_ID=$IOS_BUNDLE_ID
WATCH_BUNDLE_ID=$WATCH_BUNDLE_ID
WATCH_COMPLICATION_BUNDLE_ID=$WATCH_COMPLICATION_BUNDLE_ID
EOF

echo
echo "✓ Sims booted, apps installed."
echo "  Next: scripts/dev/tail-logs.sh"
echo "  The iOS app has NOT been launched — tail-logs.sh launches it"
echo "  AFTER the log streams are attached so startup crashes land."
