#!/bin/bash
#
# verify.sh — end-to-end sanity check for a given visionOS simulator build
#  - Niall George Horn; June 2026

# Info: 
# Confirms that:
#   1. The target runtime is installed and CoreIK.framework is present
#   2. setup.sh can copy and codesign the framework cleanly
#   3. The app builds without errors (via build.sh)
#   4. The simulator boots and the app launches (via launch.sh)
#   5. CoreIK functions actually get called (log appears with _CoreIKSolverFusion entries)
#
# Basically: does the whole thing actually work on this build, on this machine?
# Run this whenever Apple ships a new visionOS — which apparently they do constantly,
# despite having approximately nothing new to show for it feature-wise.
#
# Usage:
#   ./deploy/verify.sh                       # verify the newest installed runtime
#   COREIK_VERSION=26.5 ./deploy/verify.sh   # verify a specific version (inline env, no export needed)
#
# Version is NOT a flag here. It's set once via COREIK_VERSION (which setup.sh
# reads); this script just checks whatever build ends up staged. One job: does
# the whole thing actually work on this build, on this machine? To sweep every
# supported build in one go, use ./deploy/test_all_builds.sh.
#
# Exit codes:
#   0 — all checks passed
#   1 — something failed (check output above the failure line)
#
# Note: this boots the simulator and kills any running Simulator.app to clear
# FrontBoard state. Don't run this mid-session.
#
# /tmp is cleared on reboot — re-run setup.sh after restart.
#

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
LOG_FILE="/tmp/coreik_invocations.log"
LOG_TIMEOUT=60   # seconds to wait for first CoreIK log entry after launch

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'

pass() { echo -e "${GREEN}  ✅ $*${RESET}"; }
fail() { echo -e "${RED}  ❌ FAILED: $*${RESET}"; exit 1; }
info() { echo -e "${CYAN}  ℹ  $*${RESET}"; }
warn() { echo -e "${YELLOW}  ⚠  $*${RESET}"; }

# Version is taken from the COREIK_VERSION env var only (set it inline:
# `COREIK_VERSION=26.5 ./deploy/verify.sh`). No flags to parse — setup.sh, called
# below, reads the same env var and stages the matching runtime.
WANT_VERSION="${COREIK_VERSION:-}"

echo ""
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo -e "${BOLD}  Persona_CoreIKDemo — End-to-End Verification${RESET}"
[ -n "$WANT_VERSION" ] && echo -e "${BOLD}  Target: visionOS ${WANT_VERSION}${RESET}"
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo ""

# =========== Step 1: setup.sh ===========

echo -e "${BOLD}[1/5] Running setup.sh...${RESET}"

# No --version passed: setup.sh reads COREIK_VERSION from the environment itself.
if ! "${SCRIPT_DIR}/setup.sh" > /tmp/verify_setup.log 2>&1; then
    cat /tmp/verify_setup.log
    fail "setup.sh failed — see output above"
fi

BUILD_TAG=$(cat /tmp/CoreIK.framework/BUILD 2>/dev/null || echo "unknown")
pass "setup.sh succeeded — build ${BUILD_TAG}"

OFFSET_FILE="${SCRIPT_DIR}/coreik_offsets/${BUILD_TAG}.txt"
[ -f "$OFFSET_FILE" ] || fail "No offset file for build ${BUILD_TAG}. Run: ./deploy/derive_offsets.sh /tmp/CoreIK.framework/CoreIK"
pass "Offset file present: coreik_offsets/${BUILD_TAG}.txt"

# =========== Step 2: build.sh ===========

echo ""
echo -e "${BOLD}[2/5] Building app...${RESET}"

if ! "${SCRIPT_DIR}/build.sh" > /tmp/verify_build.log 2>&1; then
    tail -30 /tmp/verify_build.log
    fail "build.sh failed — see output above"
fi
pass "Build succeeded"

# =========== Step 3: Find UDID ===========

echo ""
echo -e "${BOLD}[3/5] Finding Vision Pro simulator...${RESET}"

UDID=$(xcrun simctl list devices 2>/dev/null \
    | grep "Apple Vision Pro" | head -1 \
    | sed -E 's/.*\(([A-F0-9-]{36})\).*/\1/')
[ -n "$UDID" ] || fail "No Apple Vision Pro simulator found. Install visionOS runtime via Xcode → Settings → Platforms."
pass "Vision Pro sim UDID: ${UDID}"

# =========== Step 4: launch.sh ===========

echo ""
echo -e "${BOLD}[4/5] Launching app...${RESET}"

if ! "${SCRIPT_DIR}/launch.sh" > /tmp/verify_launch.log 2>&1; then
    cat /tmp/verify_launch.log
    fail "launch.sh failed — see output above"
fi
pass "App launched"

# =========== Step 5: Wait for CoreIK log ===========

echo ""
echo -e "${BOLD}[5/5] Waiting for CoreIK solver output...${RESET}"
warn "Tap 'Enter Immersive Space' in the Simulator window now."
warn "Waiting up to ${LOG_TIMEOUT}s for _CoreIKSolverFusion* log entries..."

rm -f "$LOG_FILE"
WAITED=0
until [ -f "$LOG_FILE" ] && grep -q "_CoreIKSolverFusion" "$LOG_FILE" 2>/dev/null; do
    sleep 2; WAITED=$((WAITED + 2))
    if [ $WAITED -ge $LOG_TIMEOUT ]; then
        fail "No CoreIK log entries after ${LOG_TIMEOUT}s. Did you tap Enter Immersive Space?"
    fi
done

CALL_COUNT=$(grep -c "_CoreIKSolverFusion" "$LOG_FILE" 2>/dev/null || echo 0)
pass "CoreIK solver running — ${CALL_COUNT} function calls logged"

grep -q "EnableReplayMode" "$LOG_FILE" 2>/dev/null \
    && pass "EnableReplayMode confirmed in log" \
    || warn "EnableReplayMode not seen yet — may appear after first solve"

# =========== Summary ===========

echo ""
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo -e "${GREEN}${BOLD}  ✅ Verification passed — build ${BUILD_TAG}${RESET}"
echo ""
echo -e "  Move the wrist sliders to drive the skeleton."
echo -e "  Stream the live log: ${CYAN}./deploy/logs.sh${RESET}"
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo ""
