#!/usr/bin/env bash

set -euo pipefail
trap 'echo "❌ Error on line $LINENO: $BASH_COMMAND"' ERR
SENTINEL_FILE=""
# EXIT trap cleans up sentinel (if any) and reports exit code when debug
trap 'rc=$?; if [ -n "$SENTINEL_FILE" ] && [ -f "$SENTINEL_FILE" ]; then rm -f "$SENTINEL_FILE"; fi; if [ "${MACMINI_DEBUG:-0}" = "1" ]; then echo "🔚 Exit code: $rc"; fi' EXIT

# Recursion guard (some env managers may spawn subshell sourcing BASH_ENV)
if [ "${__MACMINI_ALREADY_RUNNING:-0}" = "1" ]; then
  if [ "${MACMINI_DEBUG:-0}" = "1" ]; then echo "↩️  Recursive invocation detected; exiting early"; fi
  exit 0
fi
export __MACMINI_ALREADY_RUNNING=1

# Sentinel file (phase-specific) to prevent external re-entry loops
if [ "${1:-}" = "about" ]; then
  SENTINEL_FILE="/tmp/.macmini_about_running"
  if [ -f "$SENTINEL_FILE" ]; then
    if [ "${MACMINI_DEBUG:-0}" = "1" ]; then echo "⛔ Sentinel present ($SENTINEL_FILE) - avoiding re-entry"; fi
    exit 0
  fi
  echo "$$ $(date +%s)" > "$SENTINEL_FILE" || true
fi

if [ "${MACMINI_DEBUG:-0}" = "1" ]; then
  echo "🔧 Mac Mini Manager"
  echo "Arg0=$0 Arg1=${1:-<empty>}"
  echo "BASH_ENV=${BASH_ENV:-<unset>}"
  echo "🪲 Debug enabled"
  echo "User: $(whoami)"
  echo "Shell: $SHELL"
  echo "Args: $*"
  echo ""
  set -x
fi


# ===================================================
# CONFIGURATION
# ===================================================

# Source centralized CI versions file to avoid duplication (strict; no fallbacks)
# Source centralized CI versions file (multi-path discovery with optional override)
if [ -n "${CI_VERSIONS_FILE:-}" ] && [ -f "$CI_VERSIONS_FILE" ]; then
  : # honor provided path
else
  script_dir="$(cd "$(dirname "$0")" && pwd)"
  candidate_paths=()
  [ -n "${CI_VERSIONS_FILE:-}" ] && candidate_paths+=("$CI_VERSIONS_FILE")
  candidate_paths+=(
    "$script_dir/../.ci-versions" \
    "$script_dir/.ci-versions" \
    "/tmp/.ci-versions" \
    "$PWD/.ci-versions"
  )
  if [ -d "$HOME/workspace/orchardgo" ]; then
    candidate_paths+=("$HOME/workspace/orchardgo/.ci-versions")
  fi
  found=""
  for p in "${candidate_paths[@]}"; do
    if [ -f "$p" ]; then
      CI_VERSIONS_FILE="$p"
      found=1
      break
    fi
  done
  if [ -z "$found" ]; then
    echo "❌ Required .ci-versions file not found. Tried:" >&2
    for p in "${candidate_paths[@]}"; do echo " - $p" >&2; done
    echo "Hint: provide CI_VERSIONS_FILE env or copy .ci-versions to /tmp/.ci-versions" >&2
    exit 1
  fi
fi
# shellcheck disable=SC1090
. "$CI_VERSIONS_FILE"

# Validate required variables are all present (single source of truth)
required_vars=(
  EXPECTED_MACOS_VERSION
  EXPECTED_XCODE_VERSION
  EXPECTED_IOS_RUNTIME_NAME
  EXPECTED_ANDROID_SDK_VERSION
  EXPECTED_ANDROID_BUILD_TOOLS_VERSION
  EXPECTED_ANDROID_NDK_VERSION
  EXPECTED_NODE_VERSION
  EXPECTED_RUBY_VERSION
  EXPECTED_JAVA_VERSION
)
for v in "${required_vars[@]}"; do
  if [ -z "${!v:-}" ]; then
    echo "❌ Required variable $v not set in $CI_VERSIONS_FILE" >&2
    exit 1
  fi
done

# Determine brew prefix (PATH is set up in .bashrc with mise taking precedence)
ARCH=$(uname -m 2>/dev/null || echo unknown)
if command -v brew >/dev/null 2>&1; then
    BREW_PREFIX="$(brew --prefix)"
else
    BREW_PREFIX="/usr/local"
fi

# Ensure Android SDK root variables are defined early for sterile install phase (idempotent)
if [ -z "${ANDROID_SDK_ROOT:-}" ]; then
    ANDROID_SDK_ROOT="${BREW_PREFIX}/share/android-commandlinetools"
fi
if [ -z "${ANDROID_HOME:-}" ]; then
    ANDROID_HOME="$ANDROID_SDK_ROOT"
fi
export ANDROID_SDK_ROOT ANDROID_HOME

REQUIRED_TOOLS=("mise" "xcodes" "sdkmanager")

# ===================================================
# HELPER FUNCTIONS
# ===================================================

setup_environment() {
    if [ -f "$HOME/.bashrc" ]; then
        echo "🔄 Loading environment from ~/.bashrc..."

        set +u
        source "$HOME/.bashrc"
        status=$?
        set -u

        # Safeguard: ensure PATH helper functions exist in this shell even if .bashrc incomplete
        if ! declare -f path_prepend >/dev/null 2>&1; then
            path_prepend() { case ":$PATH:" in *":$1:"*) ;; *) PATH="$1:$PATH";; esac }
        fi
        if ! declare -f path_append >/dev/null 2>&1; then
            path_append() { case ":$PATH:" in *":$1:"*) ;; *) PATH="$PATH:$1";; esac }
        fi
        if ! declare -f dedup_path >/dev/null 2>&1; then
            dedup_path() { local OLD_IFS="$IFS"; IFS=':'; set -- $PATH; IFS="$OLD_IFS"; local new=""; local seen=":"; for p in "$@"; do [ -z "$p" ] && continue; case "$seen" in *:"$p":*) ;; *) seen="$seen$p:"; new="${new:+$new:}$p";; esac; done; PATH="$new"; }
        fi
    else
        echo "⚠️  ~/.bashrc not found. Please run: $0 init"
        exit 1
    fi
}

compare_versions() {
    local installed_version="$1"
    local expected_version="$2"
    local mode="${3:-exact}"  # "exact" or "minimum"

    # Strip any suffix (e.g., -amzn)
    installed_version_clean=$(echo "$installed_version" | cut -d'-' -f1)
    expected_version_clean=$(echo "$expected_version" | cut -d'-' -f1)

    # Normalize to 3-part version: X.Y.Z
    normalize_version() {
        local version="$1"
        IFS='.' read -r major minor patch <<< "$(echo "$version" | awk -F. '{printf "%d.%d.%d", $1, ($2? $2 : 0), ($3? $3 : 0)}')"
        echo "$major.$minor.$patch"
    }

    norm_installed=$(normalize_version "$installed_version_clean")
    norm_expected=$(normalize_version "$expected_version_clean")

    if [ "$mode" = "minimum" ]; then
        # Check if installed >= expected
        if printf '%s\n%s\n' "$norm_expected" "$norm_installed" | sort -V | tail -1 | grep -qx "$norm_installed"; then
            echo "✅"
        else
            echo "❌"
        fi
    else
        # Require exact match (default for tools)
        if [ "$norm_installed" = "$norm_expected" ]; then
            echo "✅"
        else
            echo "❌"
        fi
    fi
}

# ===================================================
# CONFIGURE BASHRC
# ===================================================

configure_bash_rc() {
    echo "📦 Configuring Bash environment in ~/.bashrc..."

    # Backup existing .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        local backup_file="$HOME/.bashrc.backup.$(date +%s)"
        cp "$HOME/.bashrc" "$backup_file"
        echo "💾 Backed up existing ~/.bashrc to $backup_file"
    fi

    # Regenerate .bashrc from scratch
    echo "🔄 Regenerating ~/.bashrc..."
    cat > "$HOME/.bashrc" <<'EOF'
# PATH Helper Functions
path_prepend() { case ":$PATH:" in *":$1:"*) ;; *) PATH="$1:$PATH";; esac }
path_append() { case ":$PATH:" in *":$1:"*) ;; *) PATH="$PATH:$1";; esac }
dedup_path() {
  local OLD_IFS="$IFS"; IFS=':'; set -- $PATH; IFS="$OLD_IFS"; local new=""; local seen=":";
  for p in "$@"; do
    [ -z "$p" ] && continue
    case "$seen" in *:"$p":*) ;; *) seen="$seen$p:"; new="${new:+$new:}$p";; esac
  done
  PATH="$new"
}

# Sbin Path (set up before mise so mise tools take precedence)
path_prepend /usr/local/sbin
dedup_path

# Homebrew Path (set up before mise so mise tools take precedence)
ARCH=$(uname -m 2>/dev/null || echo unknown)
if [ "$ARCH" = "arm64" ]; then
    if [ -d /opt/homebrew/bin ]; then
        path_prepend /opt/homebrew/bin
    fi
else
    if [ -d /usr/local/bin ]; then
        path_prepend /usr/local/bin
    fi
fi
if command -v brew >/dev/null 2>&1; then
    eval "$(brew shellenv)" 2>/dev/null || true
fi
dedup_path

# mise initialization (uses ~/mise.toml automatically)
# mise paths will take precedence over Homebrew for tools defined in mise.toml
if command -v mise >/dev/null 2>&1; then
    eval "$(mise activate bash)" 2>/dev/null || true
fi

# Xcode Path
EOF
    echo "export XCODE_PATH=\"/Applications/Xcode-${EXPECTED_XCODE_VERSION}.app\"" >> "$HOME/.bashrc"
# Add dynamic fallback: detect installed Xcode matching major.minor if exact not found
cat >> "$HOME/.bashrc" <<'EOF'
if [ ! -d "$XCODE_PATH" ]; then
  # Attempt to locate an Xcode whose version starts with the expected prefix (major.minor)
  expected_prefix="$(echo "${EXPECTED_XCODE_VERSION}" | awk -F. '{print $1"."$2}')"
  best_match="$(ls -d /Applications/Xcode*.app 2>/dev/null | while read -r app; do
    ver_file="$app/Contents/version.plist"
    # Fallback to Info.plist if version.plist absent
    if [ -f "$ver_file" ]; then
      ver=$(defaults read "${app}/Contents/Info" CFBundleShortVersionString 2>/dev/null || defaults read "${app}/Contents/version" ProductBuildVersion 2>/dev/null || echo "")
    else
      ver=$(defaults read "${app}/Contents/Info" CFBundleShortVersionString 2>/dev/null || echo "")
    fi
    [ -z "$ver" ] && continue
    case "$ver" in
      ${expected_prefix}*) echo "$ver $app";;
    esac
  done | sort -V | tail -1 | awk '{print $2}')"
  if [ -n "$best_match" ] && [ -d "$best_match" ]; then
    export XCODE_PATH="$best_match"
  fi
fi
EOF
    cat >> "$HOME/.bashrc" <<'EOF'

# Android SDK Configuration (idempotent)
EOF
    echo "export ANDROID_SDK_ROOT=\"${BREW_PREFIX}/share/android-commandlinetools\"" >> "$HOME/.bashrc"
    echo "export ANDROID_HOME=\"${BREW_PREFIX}/share/android-commandlinetools\"" >> "$HOME/.bashrc"
    echo "path_prepend ${BREW_PREFIX}/share/android-commandlinetools/cmdline-tools/latest/bin" >> "$HOME/.bashrc"
    cat >> "$HOME/.bashrc" <<'EOF'
dedup_path
EOF

    echo "✅ Generated new ~/.bashrc"

    # Backup existing .bash_profile if it exists
    if [ -f "$HOME/.bash_profile" ]; then
        local backup_file="$HOME/.bash_profile.backup.$(date +%s)"
        cp "$HOME/.bash_profile" "$backup_file"
        echo "💾 Backed up existing ~/.bash_profile to $backup_file"
    fi

    # Regenerate .bash_profile
    cat > "$HOME/.bash_profile" <<'EOF'
if [ -f "$HOME/.bashrc" ]; then
    source "$HOME/.bashrc"
fi
EOF
    echo "✅ Generated new ~/.bash_profile"

    # Backup and disable .profile if it exists (may contain old RVM/NVM code)
    if [ -f "$HOME/.profile" ]; then
        local backup_file="$HOME/.profile.backup.$(date +%s)"
        mv "$HOME/.profile" "$backup_file"
        echo "💾 Backed up and disabled ~/.profile to $backup_file (may contain old RVM/NVM)"
    fi

    echo ""
    echo "🔗 .bash_profile ensures .bashrc is loaded for login shells."
    echo "🔄 Restart your terminal or run 'source ~/.bashrc' to apply changes."
}

# ===================================================
# CLEANUP COMMAND
# ===================================================

clean_machine() {
    # Usage & argument parsing (supports modes and flags)
    # Modes:
    #   light (default) - Xcode build artifacts, simulator devices, module caches, Metro/React Native temps, Android caches
    #   deep            - light + npm/yarn/Homebrew caches + Carthage/CocoaPods + SwiftPM + watchman + logs + diagnostics
    # Flags:
    #   --force            Actually delete (otherwise dry run)
    #   --mode <name>      Override mode (light|deep|custom)
    #   --keep-archives N  Keep last N days of Xcode Archives (default: 14) - only when deleting
    #   --no-simulators    Skip deleting CoreSimulator/Devices
    #   --no-device-support Skip deleting Xcode iOS DeviceSupport
    #   --include-npm      Include npm cache even in light mode
    #   --include-yarn     Include yarn cache even in light mode
    #   --only PATH        Only target the provided absolute PATH (can repeat)
    #   --help             Show usage
    # Custom mode: specify one or more --only PATH arguments OR combine include flags.

    local MODE="light"
    local FORCE=0
    local KEEP_ARCHIVES_DAYS=14
    local DELETE_SIMULATORS=1
    local DELETE_DEVICE_SUPPORT=1
    local INCLUDE_NPM=0
    local INCLUDE_YARN=0
    local ONLY_PATHS=()

    while [ $# -gt 0 ]; do
        case "$1" in
            --force) FORCE=1; shift ;;
            --mode) MODE="${2:-light}"; shift 2 ;;
            --keep-archives) KEEP_ARCHIVES_DAYS="${2:-14}"; shift 2 ;;
            --no-simulators) DELETE_SIMULATORS=0; shift ;;
            --no-device-support) DELETE_DEVICE_SUPPORT=0; shift ;;
            --include-npm) INCLUDE_NPM=1; shift ;;
            --include-yarn) INCLUDE_YARN=1; shift ;;
            --only) ONLY_PATHS+=("${2:-}"); MODE="custom"; shift 2 ;;
            --help|-h)
                echo "Usage: $0 clean [--force] [--mode light|deep|custom] [--keep-archives DAYS] [--no-simulators] [--no-device-support] [--include-npm] [--include-yarn] [--only PATH ...]";
                return 0 ;;
            *)
                echo "⚠️  Unknown clean option: $1"; shift ;;
        esac
    done

    echo "🧹 Cleaning mode: $MODE (force=$FORCE)"

    # Base targets (labels + paths)
    local CLEAN_LABELS=()
    local CLEAN_PATHS=()

    add_target() { # label path
        CLEAN_LABELS+=("$1")
        CLEAN_PATHS+=("$2")
    }

    # Shared between modes
    # (Trash target now only in deep mode)
    add_target "Xcode DerivedData" "$HOME/Library/Developer/Xcode/DerivedData"
    add_target "Xcode ModuleCache.noindex" "$HOME/Library/Developer/Xcode/ModuleCache.noindex"
    add_target "Xcode cache" "$HOME/Library/Caches/com.apple.dt.Xcode"

    if [ $DELETE_DEVICE_SUPPORT -eq 1 ]; then
        add_target "Xcode iOS DeviceSupport" "$HOME/Library/Developer/Xcode/iOS DeviceSupport"
    fi

    if [ $DELETE_SIMULATORS -eq 1 ]; then
        add_target "CoreSimulator Devices" "$HOME/Library/Developer/CoreSimulator/Devices"
    fi

    # Archives handled specially (retention)
    local ARCHIVES_PATH="$HOME/Library/Developer/Xcode/Archives"
    add_target "Xcode Archives (retention ${KEEP_ARCHIVES_DAYS}d)" "$ARCHIVES_PATH"

    # React Native / Metro bundler caches (light mode)
    add_target "Metro bundler cache (/tmp/metro-*)" "/tmp/metro-*"
    add_target "Haste map cache (/tmp/haste-map-*)" "/tmp/haste-map-*"
    add_target "React temp files (/tmp/react-*)" "/tmp/react-*"

    # Android build caches (light mode)
    add_target "Android build cache" "$HOME/.android/build-cache"
    add_target "Android cache" "$HOME/.android/cache"

    if [ "$MODE" = "deep" ] || [ "$MODE" = "custom" ]; then
        add_target "User Trash (~/.Trash contents)" "$HOME/.Trash"
        add_target "SwiftPM cache" "$HOME/Library/Caches/org.swift.swiftpm"
        add_target "Carthage cache" "$HOME/Library/Caches/carthage"
        add_target "CocoaPods cache" "$HOME/Library/Caches/CocoaPods"
        add_target "Watchman state" "$HOME/.watchman"
        add_target "Gradle cache" "$HOME/.gradle/caches"
        add_target "Gradle daemon" "$HOME/.gradle/daemon"

        # Additional deep mode cleanup targets
        add_target "CoreSimulator logs" "$HOME/Library/Logs/CoreSimulator"
        add_target "Xcode device logs" "$HOME/Library/Developer/Xcode/iOS Device Logs"
        add_target "Homebrew cache" "$HOME/Library/Caches/Homebrew"
        add_target "Android AVD snapshots" "$HOME/.android/avd/*/snapshots"
        add_target "Diagnostic reports" "$HOME/Library/Logs/DiagnosticReports"

        INCLUDE_NPM=1
        INCLUDE_YARN=1
    fi

    if [ $INCLUDE_NPM -eq 1 ]; then
        add_target "npm cache (~/.npm)" "$HOME/.npm"
    fi
    if [ $INCLUDE_YARN -eq 1 ]; then
        add_target "yarn cache" "$HOME/Library/Caches/Yarn"
    fi

    # If ONLY_PATHS provided override targets completely
    if [ ${#ONLY_PATHS[@]} -gt 0 ]; then
        CLEAN_LABELS=()
        CLEAN_PATHS=()
        local p
        for p in "${ONLY_PATHS[@]}"; do
            [ -z "$p" ] && continue
            add_target "Custom Target: $p" "$p"
        done
    fi

    echo "🧾 Planned targets:";
    local i
    local CLEAN_SIZES=()  # Array to store sizes in KB for each target
    local total_size_kb=0

    for ((i=0; i<${#CLEAN_LABELS[@]}; i++)); do
        local label="${CLEAN_LABELS[$i]}"; local path="${CLEAN_PATHS[$i]}"
        local size_kb=0

        # Handle glob patterns by expanding them
        if [[ "$path" == *"*"* ]]; then
            local expanded=($path)
            if [ ${#expanded[@]} -gt 0 ] && [ -e "${expanded[0]}" ]; then
                local count=0
                for item in "${expanded[@]}"; do
                    if [ -e "$item" ]; then
                        ((count++))
                        local item_size=$(du -sk "$item" 2>/dev/null | awk '{print $1}')
                        size_kb=$((size_kb + item_size))
                    fi
                done
                local human_size=$(awk "BEGIN {printf \"%.1fM\", $size_kb/1024}")
                echo "  • $label -> $count items ($human_size)"
            else
                echo "  • $label -> $path (no matches)"
            fi
        elif [ -d "$path" ] || [ -f "$path" ]; then
            size_kb=$(du -sk "$path" 2>/dev/null | awk '{print $1}')
            local human_size=$(du -sh "$path" 2>/dev/null | awk '{print $1}')
            echo "  • $label -> $path ($human_size)"
        else
            echo "  • $label -> $path (missing)"
        fi

        CLEAN_SIZES+=("$size_kb")
        total_size_kb=$((total_size_kb + size_kb))
    done

    # Display total size to be cleaned
    if [ $total_size_kb -gt 0 ]; then
        local total_human
        if [ $total_size_kb -ge 1048576 ]; then
            total_human=$(awk "BEGIN {printf \"%.2fG\", $total_size_kb/1048576}")
        else
            total_human=$(awk "BEGIN {printf \"%.1fM\", $total_size_kb/1024}")
        fi
        echo ""
        echo "📊 Total size to clean: $total_human"
    fi

    # Xcode Archives retention preview (when not force we just list what WOULD be removed)
    if [ -d "$ARCHIVES_PATH" ]; then
        echo "📦 Archive retention: keeping last ${KEEP_ARCHIVES_DAYS} days"
        local cutoff_ts
        cutoff_ts=$(date -v -"${KEEP_ARCHIVES_DAYS}"d +%s 2>/dev/null || date -d "-${KEEP_ARCHIVES_DAYS} days" +%s 2>/dev/null || echo 0)
        local candidate
        find "$ARCHIVES_PATH" -mindepth 2 -maxdepth 2 -type d 2>/dev/null | while read -r candidate; do
            # Expect folder names like YYYY-MM-DD_HH-MM-SS
            local base=$(basename "$candidate")
            local date_part=${base%%_*}
            if [[ "$date_part" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
                local cts=$(date -j -f "%Y-%m-%d" "$date_part" +%s 2>/dev/null || date -d "$date_part" +%s 2>/dev/null || echo 9999999999)
                if [ "$cts" -lt "$cutoff_ts" ]; then
                    echo "   - Old archive candidate: $candidate"
    if [ $FORCE -eq 1 ]; then
                        rm -rf "$candidate" 2>/dev/null || true
                    fi
                fi
            fi
        done
    fi

    # Deep mode extra action: prune unused iOS runtimes (outside target listing to avoid accidental custom mode deletions)
    if [ "$MODE" = "deep" ]; then
        echo "🧪 iOS runtime prune (deep mode) keeping ${RUNTIME_EFFECTIVE_NAME:-$EXPECTED_IOS_RUNTIME_NAME}"
        expected_runtime="${RUNTIME_EFFECTIVE_NAME:-$EXPECTED_IOS_RUNTIME_NAME}"
        if [ -n "$expected_runtime" ]; then
            for rpath in /Library/Developer/CoreSimulator/Profiles/Runtimes/*.simruntime; do
                [ -e "$rpath" ] || continue
                base=$(basename "$rpath" .simruntime)
                if [ "$base" != "$expected_runtime" ]; then
                    size=$(du -sh "$rpath" 2>/dev/null | awk '{print $1}')
                    echo "  • Old runtime candidate: $rpath ($size)"
                    if [ $FORCE -eq 1 ]; then
                        # Extract runtime UUID from Info.plist to properly unregister via simctl
                        plist="$rpath/Contents/Info.plist"
                        uuid=""
                        if [ -f "$plist" ]; then
                            # Try CFBundleIdentifier first (contains UUID in newer runtimes)
                            uuid=$(plutil -extract CFBundleIdentifier xml1 -o - "$plist" 2>/dev/null | grep -oE '([A-F0-9-]{36})' | head -n1 || true)
                            # Fallback to CFBundleUUID for older runtimes
                            if [ -z "$uuid" ]; then
                                uuid=$(plutil -extract CFBundleUUID xml1 -o - "$plist" 2>/dev/null | grep -oE '([A-F0-9-]{36})' | head -n1 || true)
                            fi
                        fi

                        if [ -n "$uuid" ]; then
                            echo "    🗑️  Removing runtime via simctl: $uuid"
                            if ! sudo xcrun simctl runtime delete "$uuid" 2>/dev/null; then
                                echo "    ⚠️  simctl failed, falling back to rm -rf: $rpath"
                                sudo rm -rf "$rpath" 2>/dev/null || echo "    ⚠️  Failed to remove (permissions): $rpath"
                            fi
                        else
                            echo "    ⚠️  Could not determine runtime UUID, removing by path: $rpath"
                            sudo rm -rf "$rpath" 2>/dev/null || echo "    ⚠️  Failed to remove (permissions): $rpath"
                        fi
                    fi
                fi
            done
        else
            echo "  ⚠️ No expected runtime variable set; skipping runtimes prune."
        fi
    fi

    if [ $FORCE -eq 1 ]; then
        echo "⚠️  Proceeding with deletion (--force specified)."
        for ((i=0; i<${#CLEAN_LABELS[@]}; i++)); do
            local label="${CLEAN_LABELS[$i]}"
            local path="${CLEAN_PATHS[$i]}"

            # Handle glob patterns by expanding them
            if [[ "$path" == *"*"* ]]; then
                local expanded=($path)
                local removed_count=0
                for item in "${expanded[@]}"; do
                    if [ -e "$item" ]; then
                        rm -rf "$item" 2>/dev/null && ((removed_count++)) || true
                    fi
                done
                if [ $removed_count -gt 0 ]; then
                    echo "🗑️  Removed $label ($removed_count items)"
                fi
            elif [ -d "$path" ] || [ -f "$path" ]; then
                if [ "$path" = "$HOME/.Trash" ]; then
                    find "$HOME/.Trash" -mindepth 1 -delete 2>/dev/null || true
                    echo "🗑️  Emptied Trash"
                else
                    rm -rf "$path" 2>/dev/null && echo "🗑️  Removed $label" || true
                fi
            fi
        done

        # Display total space saved
        if [ $total_size_kb -gt 0 ]; then
            local saved_human
            if [ $total_size_kb -ge 1048576 ]; then
                saved_human=$(awk "BEGIN {printf \"%.2fG\", $total_size_kb/1048576}")
            else
                saved_human=$(awk "BEGIN {printf \"%.1fM\", $total_size_kb/1024}")
            fi
            echo ""
            echo "💾 Space saved: $saved_human"
        fi

        echo "✅ Cleanup completed (mode=$MODE)"
    else
        echo "ℹ️  Dry run only. Add --force to delete."
    fi
}

# ===================================================
# MACOS VERSION ENFORCEMENT
# ===================================================

ensure_macos_version() {
    local current expected current_major expected_major
    current=$(sw_vers -productVersion 2>/dev/null || echo "0.0.0")
    expected="$EXPECTED_MACOS_VERSION"
    current_major=${current%%.*}
    expected_major=${expected%%.*}

    echo "🖥  macOS check: current=$current target=$expected"

    # If current already >= expected (minimum), do nothing
    if printf '%s\n%s\n' "$expected" "$current" | sort -V | tail -1 | grep -qx "$current"; then
        echo "🟢 macOS version ($current) meets or exceeds minimum ($expected)"
        return 0
    fi

    # Current < expected
    if [ "$current_major" = "$expected_major" ]; then
        echo "📦 Applying macOS minor/patch updates to reach at least $expected ..."

        # First, list available updates to see what's available
        echo "🔍 Checking available updates..."
        sudo softwareupdate --list

        # Check if we're running over SSH
        local is_ssh=0
        if [ -n "$SSH_CONNECTION" ] || [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
            is_ssh=1
        fi

        if [ "$is_ssh" = "1" ]; then
            echo "📥 Installing all recommended updates..."
            echo "⚠️  Running over SSH - system will restart and connection will drop."
            echo "🔄 Installing updates without automatic restart first..."

            # Install without restart first
            sudo softwareupdate --install --all --recommended --agree-to-license --no-scan

            echo ""
            echo "✅ Updates installed. Now restarting system..."
            echo "⏳ Connection will drop. System will be back in ~2-3 minutes."
            echo "🚪 After restart, use: yarn macmini:agent0X:wait:install (where X is your agent number)"
            echo "   This will wait for the machine to come back online, then continue installation."
            echo ""

            # Schedule restart with a small delay to allow message to be displayed
            sudo shutdown -r +1 "macOS update restart" &

            # Exit cleanly so SSH session closes gracefully
            sleep 2
            exit 0
        else
            # Local execution - can use --restart directly
            echo "📥 Installing all recommended updates..."
            echo "🔄 System will restart automatically to apply updates."
            echo "🚪 After restart, rerun: setupMacosMini.sh install"
            sudo softwareupdate --install --all --recommended --agree-to-license --restart
            exit 0
        fi
    fi

    # Major upgrade path (automatic when below minimum)
    # Space check (simple)
    local free_gb
    free_gb=$(df -g / | tail -1 | awk '{print $4}')
    if [ "${free_gb:-0}" -lt 30 ]; then
        echo "❌ Not enough free space (${free_gb}GB). Need ≥30GB for major upgrade."
        return 1
    fi

    echo "📥 Fetching full installer for $expected ..."
    if ! sudo softwareupdate --fetch-full-installer --full-installer-version "$expected"; then
        echo "❌ Failed to fetch full installer for $expected"
        return 1
    fi

    local installer_app
    installer_app=$(ls -d /Applications/Install*macOS*.app 2>/dev/null | head -n1)
    if [ -z "$installer_app" ]; then
        echo "❌ Installer application not found after fetch."
        return 1
    fi

    echo "🚀 Launching macOS major upgrade to $expected (system will reboot)."
    echo "   After reboot, rerun: ./scripts/setupMacosMini.sh install"
    echo "   Or via yarn: yarn macmini:agent0X:wait:install"
    sudo "$installer_app/Contents/Resources/startosinstall" --agreetolicense --nointeraction --forcequitapps || {
        echo "❌ startosinstall failed"
        return 1
    }
    exit 0
}

# ===================================================
# INSTALLATION COMMANDS
# ===================================================

install_required_tools() {
    echo "📦 Installing required tools..."

    # Ensure Homebrew is installed (attempt to load if not already in PATH)
    if ! command -v brew &> /dev/null; then
        if [ -x /opt/homebrew/bin/brew ]; then
            eval "$(/opt/homebrew/bin/brew shellenv)"
        elif [ -x /usr/local/bin/brew ]; then
            export PATH="/usr/local/bin:$PATH"
        fi
    fi

    if ! command -v brew &> /dev/null; then
        echo "❌ Homebrew is not installed. Please install it first from https://brew.sh/"
        exit 1
    fi

    brew update

    # Install GPG if not present
    if ! command -v gpg &> /dev/null; then
        echo "📦 Installing GPG..."
        brew install gnupg
    else
        echo "🟢 GPG is already installed."
    fi

    # Install ncdu (disk usage analyzer)
    if ! brew list ncdu &> /dev/null; then
        echo "📦 Installing ncdu via Homebrew..."
        brew install ncdu
    else
        echo "🟢 ncdu is already installed."
    fi

    # Install tools
    for tool in "${REQUIRED_TOOLS[@]}"; do
        case $tool in
            "mise")
                if ! brew list mise &> /dev/null; then
                    echo "📦 Installing mise via Homebrew..."
                    brew install mise
                else
                    echo "🟢 mise is already installed."
                fi
                ;;
            "xcodes")
                if ! brew list xcodes &> /dev/null; then
                    echo "📦 Installing xcodes via Homebrew..."
                    brew install xcodes
                else
                    echo "🟢 xcodes is already installed."
                fi
                ;;
            "sdkmanager")
                if brew list --cask android-commandlinetools &> /dev/null; then
                    echo "🟢 android-commandlinetools (sdkmanager) is already installed via Homebrew."
                else
                    echo "📦 Installing Android SDK Command Line Tools via Homebrew..."
                    brew install --cask android-commandlinetools
                    echo "✅ Android SDK Command Line Tools installed via Homebrew."
                fi
                ;;
        esac
    done

    echo "✅ All required tools installed."
}

# Removed: install_node_via_homebrew, install_ruby_via_homebrew, install_java_via_homebrew
# These are now handled by mise

install_android_sdk() {
    echo "📦 Installing Android SDK (API $EXPECTED_ANDROID_SDK_VERSION, Build Tools $EXPECTED_ANDROID_BUILD_TOOLS_VERSION)..."


    # Install cmdline-tools;latest first if not present
    CMDLINE_TOOLS_LATEST="$ANDROID_SDK_ROOT/cmdline-tools/latest"
    if [ ! -d "$CMDLINE_TOOLS_LATEST" ]; then
        echo "📦 Installing cmdline-tools;latest..."
        sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install "cmdline-tools;latest"
    else
        echo "🟢 cmdline-tools;latest already exists, skipping."
    fi

    # Install platforms;android-XX if not present
    PLATFORM_DIR="$ANDROID_SDK_ROOT/platforms/android-${EXPECTED_ANDROID_SDK_VERSION}"
    if [ ! -d "$PLATFORM_DIR" ]; then
        echo "📦 Installing platforms;android-${EXPECTED_ANDROID_SDK_VERSION}..."
        sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install "platforms;android-${EXPECTED_ANDROID_SDK_VERSION}"
    else
        echo "🟢 platforms;android-${EXPECTED_ANDROID_SDK_VERSION} already exists, skipping."
    fi

    # Install build-tools;XX.X.X if not present
    BUILD_TOOLS_DIR="$ANDROID_SDK_ROOT/build-tools/${EXPECTED_ANDROID_BUILD_TOOLS_VERSION}"
    if [ ! -d "$BUILD_TOOLS_DIR" ]; then
        echo "📦 Installing build-tools;${EXPECTED_ANDROID_BUILD_TOOLS_VERSION}..."
        sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install "build-tools;${EXPECTED_ANDROID_BUILD_TOOLS_VERSION}"
    else
        echo "🟢 build-tools;${EXPECTED_ANDROID_BUILD_TOOLS_VERSION} already exists, skipping."
    fi

    # Install platform-tools if not present (check for adb)
    if [ ! -f "$ANDROID_SDK_ROOT/platform-tools/adb" ]; then
        echo "📦 Installing platform-tools..."
        sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install "platform-tools"
    else
        echo "🟢 platform-tools already exists, skipping."
    fi

    # Remove any unexpected NDK versions (keep only the expected version)
    if [ -d "$ANDROID_SDK_ROOT/ndk" ]; then
        echo "🔍 Checking for unexpected NDK versions..."
        for ndk_version in "$ANDROID_SDK_ROOT/ndk"/*; do
            if [ -d "$ndk_version" ]; then
                version_name=$(basename "$ndk_version")
                if [ "$version_name" != "$EXPECTED_ANDROID_NDK_VERSION" ]; then
                    echo "🗑️  Removing unexpected NDK version: $version_name"
                    sdkmanager --uninstall "ndk;$version_name" || true
                fi
            fi
        done
    fi

    # Install NDK if not present
    NDK_DIR="$ANDROID_SDK_ROOT/ndk/${EXPECTED_ANDROID_NDK_VERSION}"
    if [ ! -d "$NDK_DIR" ]; then
        echo "📦 Installing Android NDK ${EXPECTED_ANDROID_NDK_VERSION}..."
        sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install "ndk;${EXPECTED_ANDROID_NDK_VERSION}"
    else
        echo "🟢 ndk;${EXPECTED_ANDROID_NDK_VERSION} already exists, skipping."
    fi

    echo "📄 Accepting Android SDK licenses..."
    yes | sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --licenses

    echo "✅ Android SDK install completed."
}

install_xcode() {
    local xcode_app="/Applications/Xcode-$EXPECTED_XCODE_VERSION.app"
    echo "📦 Ensuring Xcode $EXPECTED_XCODE_VERSION is installed..."

    if [ -d "$xcode_app" ]; then
        echo "🟢 Xcode $EXPECTED_XCODE_VERSION already installed at $xcode_app"
    else
        echo "📥 Downloading / Installing Xcode $EXPECTED_XCODE_VERSION via xcodes..."
        if ! xcodes install "$EXPECTED_XCODE_VERSION"; then
            echo "❌ Failed to install Xcode $EXPECTED_XCODE_VERSION via xcodes"
            return 1
        fi
    fi

    local current_xcode expected_path
    current_xcode=$(xcode-select -p 2>/dev/null || echo "")
    expected_path="$xcode_app/Contents/Developer"

    if [ "$current_xcode" = "$expected_path" ]; then
        echo "🟢 Xcode $EXPECTED_XCODE_VERSION already selected"
    else
        echo "🔄 Selecting Xcode $EXPECTED_XCODE_VERSION (requires sudo)..."
        # Switch and accept license (idempotent)
        sudo xcode-select --switch "$xcode_app" || echo "⚠️ xcode-select switch failed"
        sudo xcodebuild -license accept || echo "⚠️ license accept may have failed (might already be accepted)"
        sudo xcodebuild -runFirstLaunch || echo "⚠️ xcodebuild -runFirstLaunch failed or already complete"
        sudo DevToolsSecurity -enable || true
    fi

    # Ensure at least one iPhoneOS SDK is present (builds for Any iOS Device require it)
    if [ "$current_xcode" != "$expected_path" ]; then
        if ! xcodebuild -showsdks 2>/dev/null | grep -qi 'iphoneos'; then
            echo "⚠️ iPhoneOS SDK not detected via 'xcodebuild -showsdks'. Attempting download of iOS platform..."
            # Try targeted platform first
            if ! sudo xcodebuild -downloadPlatform iOS 2>/dev/null; then
                echo "⚠️ Targeted iOS platform download failed, attempting full platforms download..."
                sudo xcodebuild -downloadPlatforms 2>/dev/null || echo "❌ Could not trigger platform downloads (may require GUI)."
            fi
            # Re-check
            if xcodebuild -showsdks 2>/dev/null | grep -qi 'iphoneos'; then
                echo "✅ iPhoneOS SDK now available after download attempt."
            else
                echo "❌ iPhoneOS SDK still missing. You may need to: open Xcode → Settings → Platforms and install the required iOS SDK manually, then re-run 'yarn macmini:agent0X:install'."
            fi
        else
            echo "🟢 iPhoneOS SDK detected."
        fi
    fi

    if ! pkgutil --pkg-info=com.apple.pkg.CLTools_Executables &>/dev/null; then
        echo "📦 Installing Xcode Command Line Tools (requires sudo)..."
        sudo xcode-select --install || echo "⚠️ CLI tools GUI installer triggered (may require manual intervention)"
    else
        echo "🟢 Xcode Command Line Tools already installed."
    fi
}

# ===================================================
# iOS RUNTIME & SIMULATORS
# Simulator device category resolution
# Categories allow a stable intent-based list without hardcoding model names.
# Supported default categories (can expand later):
#   iphone_latest  -> Highest available standard iPhone (e.g., iPhone 16)
#   iphone_se      -> Latest iPhone SE generation (e.g., iPhone SE (3rd generation))
#   ipad_latest    -> Latest base iPad (e.g., iPad (10th generation))
# Users can override with SIM_DEVICES (semicolon separated names) to bypass categories.
# Or override categories sequence with SIM_DEVICE_CATEGORIES (semicolon separated categories).
# Debug mapping with SIM_CATEGORY_DEBUG=1.
resolve_simulator_categories() {
    local categories_list resolved names_json devicetypes_json existing_devices runtime_line runtime_id

    # If SIM_DEVICES provided, we do not resolve categories here.
    if [ -n "${SIM_DEVICES:-}" ]; then
        echo ""; return 0
    fi

    # Default to iphone_latest only for faster CI builds.
    # Previously tested iphone_latest;iphone_se;ipad_latest but reduced to single device.
    # Override with SIM_DEVICE_CATEGORIES env var if broader coverage needed.
    categories_list="${SIM_DEVICE_CATEGORIES:-iphone_latest}";

    # Collect device types and existing devices once
    devicetypes_json=$(xcrun simctl list devicetypes 2>/dev/null || true)
    existing_devices=$(xcrun simctl list devices 2>/dev/null || true)

    # We'll attempt to detect the highest numbered iPhone / iPad etc.
    local resolved_devices="";

    IFS=';' read -r -a cat_arr <<< "$categories_list"
    local cat
    for cat in "${cat_arr[@]}"; do
        cat=$(echo "$cat" | sed 's/^ *//;s/ *$//')
        [ -z "$cat" ] && continue
        local match=""
        case "$cat" in
            iphone_latest)
                # Extract iPhone <number> device types, pick highest
                match=$(echo "$devicetypes_json" | awk -F'[()]' '/iPhone [0-9]+ \(/ {print $1}' | sed -E 's/^ *- *//' | awk '/iPhone [0-9]+$/{print}' | sed -E 's/.*iPhone ([0-9]+)/\1 iPhone &/' | awk '{printf "%03d %s\n", $1, $2" "$3}' | sort | tail -1 | cut -d' ' -f2-)
                ;;
            iphone_se)
                # Prefer explicit SE (3rd generation) then fallback to latest SE
                match=$(echo "$devicetypes_json" | grep -F "iPhone SE (3rd generation)" | head -1 | sed -E 's/^ *- *//' || true)
                if [ -z "$match" ]; then
                    match=$(echo "$devicetypes_json" | grep -F "iPhone SE (" | tail -1 | sed -E 's/^ *- *//' || true)
                fi
                ;;
            ipad_latest)
                # Match iPad (<Nth> generation)
                match=$(echo "$devicetypes_json" | awk -F'[()]' '/iPad \([0-9]+th generation\)/{print $1}' | sed -E 's/^ *- *//' | sed -E 's/.*iPad \(([0-9]+)th generation\)/\1 &/' | awk '{printf "%03d %s\n", $1, $2" "$3" "$4" "$5}' | sort | tail -1 | cut -d' ' -f2-)
                # Fallback if not found
                if [ -z "$match" ]; then
                    match=$(echo "$devicetypes_json" | grep -E "iPad \(" | tail -1 | sed -E 's/^ *- *//' || true)
                fi
                ;;
            *)
                # Unknown category, emit as-is (user might have added new literal name)
                match="$cat"
                ;;
        esac
        if [ -n "$match" ]; then
            # Strip trailing device type identifier in parentheses if present
            match=$(echo "$match" | sed -E 's/ \(com\.apple\.CoreSimulator\.SimDeviceType\.[^)]*\)$//')
            resolved_devices+="$match;"
            [ "${SIM_CATEGORY_DEBUG:-0}" = "1" ] && echo "🔎 Category $cat -> $match"
        else
            [ "${SIM_CATEGORY_DEBUG:-0}" = "1" ] && echo "⚠️  Category $cat could not resolve a device name"
        fi
    done

    # Trim trailing semicolon
    resolved_devices=$(echo "$resolved_devices" | sed 's/;*$//')
    echo "$resolved_devices"
}
# ===================================================

ensure_ios_runtime() {
    # Enhanced logic with proactive platform download:
    # 1. If configured runtime exists -> use it.
    # 2. If missing, first attempt iOS platform download via `xcodebuild -downloadPlatform iOS` (once per configured runtime).
    # 3. Poll (default 30m) for the configured runtime to appear (directory or simctl list).
    # 4. Only after timeout / failure do we fallback to highest installed / available runtime.
    # 5. Preserve original EXPECTED_IOS_RUNTIME_NAME; export effective as RUNTIME_EFFECTIVE_NAME.

    if [ "${SKIP_RUNTIME_INSTALL:-0}" = "1" ]; then
        echo "⏭️  Skipping iOS runtime install (SKIP_RUNTIME_INSTALL=1)."
        return 0
    fi

    echo "📱 Checking for iOS Runtime (configured): $EXPECTED_IOS_RUNTIME_NAME"

    local configured_runtime="$EXPECTED_IOS_RUNTIME_NAME"
    local runtime_dir="/Library/Developer/CoreSimulator/Profiles/Runtimes/${configured_runtime}.simruntime"
    local installed_runtimes
    installed_runtimes=$(xcrun simctl list runtimes 2>/dev/null | grep -E '^iOS [0-9]+\.' || true)

    local configured_present=0
    if echo "$installed_runtimes" | grep -F "$configured_runtime" >/dev/null 2>&1; then
        configured_present=1
    elif [ -d "$runtime_dir" ]; then
        configured_present=1
    fi

    # If configured runtime already available, short‑circuit
    if [ $configured_present -eq 1 ]; then
        export RUNTIME_EFFECTIVE_NAME="$configured_runtime"
        echo "🟢 Configured runtime already installed: $configured_runtime"
    else
        echo "⚠️  Configured runtime not installed: $configured_runtime"
        # Attempt proactive platform download before fallback
        local marker="/tmp/.ios_platform_download_${configured_runtime// /_}.started"
        local download_attempted=0
        if [ -f "$marker" ]; then
            download_attempted=1
            echo "ℹ️  Platform download previously initiated (marker present: $marker)."
        fi

        if [ $download_attempted -eq 0 ] && [ "${SKIP_IOS_PLATFORM_DOWNLOAD:-0}" != "1" ]; then
            echo "📥 Initiating iOS platform download via xcodebuild (one-time per configured runtime)..."
            if sudo xcodebuild -downloadPlatform iOS 2>&1 | sed 's/^/   xcodebuild: /'; then
                echo "🟢 xcodebuild -downloadPlatform iOS command executed (download may continue in background)."
            else
                echo "⚠️  xcodebuild -downloadPlatform iOS command failed (continuing to poll / fallback)."
            fi
            date +%s > "$marker" || true
            download_attempted=1
        fi

        # Poll for appearance of configured runtime if download attempted
        if [ $download_attempted -eq 1 ]; then
            local poll_timeout="${IOS_RUNTIME_DOWNLOAD_TIMEOUT_SECONDS:-1800}"   # 30m default
            local poll_interval="${IOS_RUNTIME_POLL_INTERVAL_SECONDS:-30}"        # 30s default
            local start_ts=$(date +%s)
            local elapsed=0
            echo "⏳ Waiting up to ${poll_timeout}s for runtime $configured_runtime to appear (interval ${poll_interval}s)..."
            while :; do
                # Refresh detection
                installed_runtimes=$(xcrun simctl list runtimes 2>/dev/null | grep -E '^iOS [0-9]+\.' || true)
                if echo "$installed_runtimes" | grep -F "$configured_runtime" >/dev/null 2>&1 || [ -d "$runtime_dir" ]; then
                    echo "✅ Detected configured runtime after $elapsed seconds: $configured_runtime"
                    export RUNTIME_EFFECTIVE_NAME="$configured_runtime"
                    configured_present=1
                    break
                fi
                elapsed=$(( $(date +%s) - start_ts ))
                if [ $elapsed -ge $poll_timeout ]; then
                    echo "⌛ Timeout (${poll_timeout}s) waiting for runtime $configured_runtime; proceeding to fallback logic."
                    break
                fi
                # Progress metric (directory size if partially downloaded)
                if [ -d "$runtime_dir" ]; then
                    local size
                    size=$(du -sh "$runtime_dir" 2>/dev/null | awk '{print $1}')
                    echo "   ... still downloading (${elapsed}s elapsed, partial size=$size)"
                else
                    echo "   ... not present yet (${elapsed}s elapsed)"
                fi
                sleep "$poll_interval"
            done
        fi

        # Fallback selection if still not present
        if [ $configured_present -ne 1 ]; then
            local effective_runtime=""
            local highest_installed
            highest_installed=$(echo "$installed_runtimes" | sed -E 's/^(iOS [0-9]+\.[0-9]+).*$/\1/' | sort -V | tail -1)
            if [ -n "$highest_installed" ]; then
                echo "➡️  Using highest installed runtime fallback: $highest_installed"
                effective_runtime="$highest_installed"
            else
                echo "🔍 No local runtimes installed yet. Querying available runtimes via xcodes..."
                local available highest_available
                available=$(xcodes runtimes --list 2>/dev/null | grep -E '^iOS [0-9]+\.[0-9]+' | sed -E 's/\s+\(Installed\)//' || true)
                if [ -n "$available" ]; then
                    highest_available=$(echo "$available" | sed -E 's/^(iOS [0-9]+\.[0-9]+).*$/\1/' | sort -V | tail -1)
                    if [ -n "$highest_available" ]; then
                        echo "➡️  Selecting highest available runtime: $highest_available"
                        effective_runtime="$highest_available"
                    fi
                fi
            fi

            if [ -z "$effective_runtime" ]; then
                echo "❌ Could not determine an effective runtime (no installed or available candidates)."
                echo "   Check Xcode installation and rerun."
                return 1
            fi
            export RUNTIME_EFFECTIVE_NAME="$effective_runtime"
            echo "🧩 Effective runtime (fallback): $RUNTIME_EFFECTIVE_NAME (configured: $configured_runtime)"
        else
            echo "🧩 Effective runtime: $configured_runtime (configured)"
        fi
    fi

    # At this point RUNTIME_EFFECTIVE_NAME is set.
    local runtime_dir_effective="/Library/Developer/CoreSimulator/Profiles/Runtimes/${RUNTIME_EFFECTIVE_NAME}.simruntime"
    local simctl_line runtime_id
    simctl_line=$(xcrun simctl list runtimes 2>/dev/null | grep -F "$RUNTIME_EFFECTIVE_NAME" | head -n1 || true)
    if [ -n "$simctl_line" ]; then
        runtime_id="${simctl_line##*- }"
    fi

    if [ -d "$runtime_dir_effective" ] || [ -n "$runtime_id" ]; then
        echo "🟢 iOS Runtime appears installed (${runtime_id:-directory present})."
        return 0
    fi

    echo "📥 iOS Runtime not present after selection. Attempting install via xcodes..."
    local attempt=1 max_attempts=3
    while [ $attempt -le $max_attempts ]; do
        echo "➡️  Runtime install attempt $attempt/$max_attempts for $RUNTIME_EFFECTIVE_NAME"
        if output=$(xcodes runtimes install "$RUNTIME_EFFECTIVE_NAME" 2>&1); then
            echo "✅ Runtime install reported success. Re-checking..."
        else
            echo "$output" | grep -qi "Authorization is required" && {
                echo "⚠️  Authorization required and not granted in headless session. Skipping further attempts.";
                break;
            }
            echo "⚠️  Attempt $attempt failed."
        fi
        if xcrun simctl list runtimes | grep -F "$RUNTIME_EFFECTIVE_NAME" >/dev/null 2>&1; then
            echo "🟢 iOS Runtime now installed."
            return 0
        fi
        attempt=$((attempt+1))
        sleep 6
    done

    if ! xcrun simctl list runtimes | grep -F "$RUNTIME_EFFECTIVE_NAME" >/dev/null 2>&1; then
        echo "❌ Could not confirm iOS Runtime installation after $max_attempts attempts (non-fatal)."
        echo "   Installed runtimes were:"
        echo "$installed_runtimes" | sed 's/^/   • /'
        echo "   Hint: Configured=$configured_runtime Effective=$RUNTIME_EFFECTIVE_NAME."
        echo "         If configured name is synthetic or future, ensure platform download completes or install manually via Xcode GUI."
    fi
}

ensure_simulator_devices() {
    # Default to creating devices unless explicitly disabled
    if [ "${CREATE_DEFAULT_SIMULATORS:-1}" != "1" ]; then
        echo "⏭️  Skipping simulator device creation (CREATE_DEFAULT_SIMULATORS!=1)."
        return 0
    fi

    echo "📲 Ensuring baseline simulator devices exist..."

    # Derive runtime identifier (best effort) from simctl output
    local runtime_line runtime_id
    runtime_line=$(xcrun simctl list runtimes 2>/dev/null | grep -F "${RUNTIME_EFFECTIVE_NAME:-$EXPECTED_IOS_RUNTIME_NAME}" | head -n1 || true)
    if [ -n "$runtime_line" ]; then
        runtime_id="${runtime_line##*- }"
    fi

    if [ -z "$runtime_id" ]; then
        echo "⚠️  Cannot determine runtime identifier for ${RUNTIME_EFFECTIVE_NAME:-$EXPECTED_IOS_RUNTIME_NAME}; skipping device creation."
        return 0
    fi

    # Allow overriding device list via SIM_DEVICES (semicolon-separated to avoid issues with commas in names)
    # Example: SIM_DEVICES="iPhone 16;iPhone SE (3rd generation);iPad (10th generation)"
    local default_devices="iPhone 16;iPhone SE (3rd generation);iPad (10th generation)"

    local device_list
    if [ -n "${SIM_DEVICES:-}" ]; then
        device_list="$SIM_DEVICES"
    else
        # Resolve categories to device names; fallback to previous static default if empty
        local resolved_categories
        resolved_categories=$(resolve_simulator_categories)
        if [ -n "$resolved_categories" ]; then
            device_list="$resolved_categories"
        else
            device_list="$default_devices"
        fi
    fi

    # Marker file to short‑circuit if devices already ensured for this runtime+set
    local marker_sig
    local marker_file="$HOME/.sim_devices_${RUNTIME_EFFECTIVE_NAME// /_}.stamp"
    marker_sig=$(echo "$device_list|$runtime_id|${SIM_DEVICE_CATEGORIES:-none}" | shasum | awk '{print $1}')

    local existing_devices
    existing_devices=$(xcrun simctl list devices 2>/dev/null || true)

    local all_present=1
    IFS=';' read -r -a names <<< "$device_list"
    for name in "${names[@]}"; do
        if ! echo "$existing_devices" | grep -F "$name (" >/dev/null 2>&1; then
            all_present=0
            break
        fi
    done

    if [ -f "$marker_file" ] && grep -q "$marker_sig" "$marker_file" && [ $all_present -eq 1 ]; then
        echo "🟢 All requested simulators already present (marker matched). Skipping creation."
        return 0
    fi

    # Cache device types list once
    local devicetypes_json
    devicetypes_json=$(xcrun simctl list devicetypes 2>/dev/null || true)

    local name
    for name in "${names[@]}"; do
        # Trim leading/trailing spaces and remove accidental embedded device type identifiers
        name="$(echo "$name" | sed 's/^ *//;s/ *$//' | sed -E 's/ \(com\.apple\.CoreSimulator\.SimDeviceType\.[^)]*\)//')"
        if [ -z "$name" ]; then
            continue
        fi
        if echo "$existing_devices" | grep -F "$name (" >/dev/null 2>&1; then
            echo "🟢 Device '$name' already exists."
            continue
        fi

        # Attempt to discover exact device type identifier for the name
        local dtype
        dtype=$(echo "$devicetypes_json" | awk -v n="$name" -F'[()]' '$0 ~ n {gsub(/^[ \t-]+|[ \t]+$/,"",$2); print $2; exit}')

        if [ -z "$dtype" ]; then
            # Heuristic fallback: transform name to canonical slug
            # iPhone 16 -> iPhone-16 ; iPhone SE (3rd generation) -> iPhone-SE-3rd-generation
            local slug
            slug=$(echo "$name" | sed -E 's/\(//;s/\)//;s/ generation//;s/ /-/g;s/--*/-/g')
            dtype="com.apple.CoreSimulator.SimDeviceType.$slug"
        fi

        # Fix known correct iPad 10th generation identifier explicitly
        if echo "$name" | grep -qi "iPad (10th generation)"; then
            dtype="com.apple.CoreSimulator.SimDeviceType.iPad-10th-generation"
        fi

        echo "➕ Creating simulator '$name' (type=$dtype runtime=$runtime_id) ..."
        if xcrun simctl create "$name" "$dtype" "$runtime_id" >/dev/null 2>&1; then
            echo "✅ Created '$name'"
        else
            echo "⚠️  Initial create failed for '$name' with type '$dtype'. Attempting alternate inference..."
            # Broader inference: pick first device type line containing cleaned base (without parenthetical)
            local base
            base=$(echo "$name" | sed 's/ (.*)//')
            local inferred
            inferred=$(echo "$devicetypes_json" | grep -i "$base" | awk -F'[()]' 'NR==1{gsub(/^[ \t-]+|[ \t]+$/,"",$2); print $2}' || true)
            if [ -n "$inferred" ] && [ "$inferred" != "$dtype" ]; then
                echo "➡️  Retrying with inferred type: $inferred"
                if xcrun simctl create "$name" "$inferred" "$runtime_id" >/dev/null 2>&1; then
                    echo "✅ Created '$name' with inferred type"
                else
                    echo "❌ Could not create simulator '$name' (non-fatal)."
                fi
            else
                echo "❌ Could not create simulator '$name' (non-fatal)."
            fi
        fi
    done

    # Refresh existing devices after attempts
    existing_devices=$(xcrun simctl list devices 2>/dev/null || true)

    # Re-evaluate presence
    all_present=1
    for name in "${names[@]}"; do
        if ! echo "$existing_devices" | grep -F "$name (" >/dev/null 2>&1; then
            all_present=0
            break
        fi
    done

    if [ $all_present -eq 1 ]; then
        echo "$marker_sig" > "$marker_file" || true
    fi

    echo "📋 Post-creation device summary (filtered):"
    echo "$existing_devices" | grep -Ev '^Install (Started|Failed)' | grep -E "$(echo "$device_list" | sed 's/;/|/g')" || echo "⚠️  No requested devices found."
}


# ===================================================
# SETUP COMMANDS
# ===================================================

install_mise_tools() {
    echo "📦 Installing tools via mise (using ~/mise.toml)..."

    # Ensure mise is available
    if ! command -v mise >/dev/null 2>&1; then
        echo "❌ mise not found in PATH" >&2
        return 1
    fi

    # Activate mise in current shell
    eval "$(mise activate bash)" || true

    # Trust the mise.toml file in home directory before using it
    echo "🔐 Trusting ~/mise.toml..."
    if ! mise trust ~/mise.toml; then
        echo "⚠️  Failed to trust ~/mise.toml (non-fatal, continuing...)"
    fi

    # Install tools from ~/mise.toml (mise auto-discovers it)
    echo "📦 Installing from ~/mise.toml..."
    mise install || {
        echo "⚠️  mise install failed"
        return 1
    }

    echo "✅ Tools installed via mise from ~/mise.toml."
}

ensure_node_version() {
    if ! command -v mise >/dev/null 2>&1; then
        echo "❌ mise not available; cannot enforce Node version" >&2
        return 1
    fi
    eval "$(mise activate bash)" 2>/dev/null || true
}

ensure_ruby_version() {
    if ! command -v mise >/dev/null 2>&1; then
        echo "❌ mise not available; cannot enforce Ruby version" >&2
        return 1
    fi
    eval "$(mise activate bash)" 2>/dev/null || true
}

# ===================================================
# SYSTEM INFO
# ===================================================

verify_path_integrity() {
    # Reports duplicate entries and ensures required dirs are present
    local IFS=':' entry seen="" duplicates=""; local required=("/usr/local/sbin" "$BREW_PREFIX/bin")
    for entry in $PATH; do
        [ -z "$entry" ] && continue
        case ":$seen:" in
            *":$entry:"*) duplicates+="$entry\n" ;;
            *) seen+="$entry:" ;;
        esac
    done
    if [ -n "$duplicates" ]; then
        echo "⚠️  PATH duplicates detected:"; echo -e "$duplicates" | sort -u
    else
        echo "🟢 PATH contains no duplicates"
    fi
    for req in "${required[@]}"; do
        case ":$PATH:" in *":$req:"*) ;; *) echo "⚠️  Required path missing: $req" ;; esac
    done
}

display_about() {
    if [ -f /tmp/.macmini_about_running ] && [ "${MACMINI_DEBUG:-0}" = "1" ]; then
        echo "🧪 display_about start (sentinel exists) pid=$$"
    fi
    # Lightweight environment loading: avoid sourcing full ~/.bashrc (causes recursion)
    # If sentinel exists and we've already sourced once, skip re-sourcing env managers
    if [ -f /tmp/.macmini_about_running ] && grep -q "^$$ " /tmp/.macmini_about_running 2>/dev/null; then
        [ "${MACMINI_DEBUG:-0}" = "1" ] && echo "🛑 Skipping env sourcing on re-entry for same PID $$"
    elif [ "${FORCE_BASHRC:-0}" = "1" ] && [ -f "$HOME/.bashrc" ]; then
        [ "${MACMINI_DEBUG:-0}" = "1" ] && echo "🔎 FORCE_BASHRC=1 sourcing ~/.bashrc"
        # shellcheck disable=SC1090
        source "$HOME/.bashrc" >/dev/null 2>&1 || true
    else
        [ "${MACMINI_DEBUG:-0}" = "1" ] && echo "🔎 Loading tool envs directly (no ~/.bashrc)"
        # Activate mise for tool version management (uses ~/mise.toml automatically)
        if command -v mise >/dev/null 2>&1; then
            eval "$(mise activate bash)" >/dev/null 2>&1 || true
        fi
        verify_path_integrity || true
    fi

    # Safe collection of versions without triggering pipefail exits if tools missing
    local macos_version
    macos_version=$(sw_vers -productVersion 2>/dev/null || echo "Unknown")

    local xcode_version
    if command -v xcodebuild >/dev/null 2>&1; then
        xcode_version=$(xcodebuild -version 2>/dev/null | grep 'Xcode' | sed 's/Xcode //' || echo "Unknown")
    else
        xcode_version="Not Installed"
    fi

    local xcode_cli_installed
    if xcode-select -p &>/dev/null; then
        xcode_cli_installed="✅"
    else
        xcode_cli_installed="❌"
    fi

    # Determine highest installed Android SDK platform version (single value for comparison)
    local android_sdk_versions android_sdk_installed
    if command -v sdkmanager >/dev/null 2>&1; then
        # Wrap in subshell to avoid pipefail terminating the script
        android_sdk_versions=$( (sdkmanager --list_installed 2>/dev/null || true) | awk -F';' '/platforms;android-[0-9]+/{print $2}' | sed 's/^android-//' | awk '{print $1}')
    else
        android_sdk_versions=""
    fi
    if [ -n "$android_sdk_versions" ]; then
        android_sdk_installed=$(echo "$android_sdk_versions" | awk 'NF{split($0,a,"."); printf "%03d.%03d.%03d %s\n", a[1], (a[2]?a[2]:0), (a[3]?a[3]:0), $0}' | sort | tail -1 | awk '{print $2}')
    else
        android_sdk_installed="Not Installed"
    fi

    # Determine highest installed Android Build Tools version (single value for comparison)
    local android_build_tools_versions android_build_tools_installed
    if command -v sdkmanager >/dev/null 2>&1; then
        android_build_tools_versions=$( (sdkmanager --list_installed 2>/dev/null || true) | awk -F';' '/build-tools;[0-9]+\./{print $2}' | awk '{print $1}')
    else
        android_build_tools_versions=""
    fi
    if [ -n "$android_build_tools_versions" ]; then
        android_build_tools_installed=$(echo "$android_build_tools_versions" | awk 'NF{split($0,a,"."); printf "%03d.%03d.%03d %s\n", a[1], (a[2]?a[2]:0), (a[3]?a[3]:0), $0}' | sort | tail -1 | awk '{print $2}')
    else
        android_build_tools_installed="Not Installed"
    fi

    # Node detection (managed by mise)
    local node_version
    if command -v node >/dev/null 2>&1; then
        node_version=$(node -v 2>/dev/null | sed 's/v//g')
    else
        node_version="Not Installed"
    fi

    # Ruby detection (managed by mise)
    local ruby_version
    if command -v ruby >/dev/null 2>&1; then
        ruby_version=$(ruby -v 2>/dev/null | awk '{print $2}')
    else
        ruby_version="Not Installed"
    fi

    local java_version
    if command -v java >/dev/null 2>&1; then
        java_version=$(java -version 2>&1 | head -n1 | awk -F'"' '{print $2}')
    else
        java_version="Not Installed"
    fi

    # Version manager version (mise)
    local mise_version
    if command -v mise >/dev/null 2>&1; then
        mise_version=$(mise --version 2>/dev/null | awk '{print $1}' || echo "Installed")
    else
        mise_version="Not Installed"
    fi

    local xcode_cli_version
    if xcode-select -p &>/dev/null; then
        xcode_cli_version=$(pkgutil --pkg-info=com.apple.pkg.CLTools_Executables 2>/dev/null | grep version | awk '{print $2}' || echo "Installed")
    else
        xcode_cli_version="Not Installed"
    fi

    # React Native tooling versions
    local yarn_version
    if command -v yarn >/dev/null 2>&1; then
        yarn_version=$(yarn --version 2>/dev/null || echo "Error")
    else
        yarn_version="Not Installed"
    fi

    local bundler_version
    if command -v bundle >/dev/null 2>&1; then
        bundler_version=$(bundle --version 2>/dev/null | awk '{print $3}' || echo "Error")
    else
        bundler_version="Not Installed"
    fi

    local git_version
    if command -v git >/dev/null 2>&1; then
        git_version=$(git --version 2>/dev/null | awk '{print $3}' || echo "Error")
    else
        git_version="Not Installed"
    fi

    # Android NDK version
    local android_ndk_installed="Not Installed"
    if [ -d "$ANDROID_SDK_ROOT/ndk" ]; then
        local ndk_versions
        ndk_versions=$(ls -1 "$ANDROID_SDK_ROOT/ndk" 2>/dev/null | sort -V | tail -1)
        if [ -n "$ndk_versions" ]; then
            android_ndk_installed="$ndk_versions"
        fi
    fi

    # System resources
    local memory_info
    memory_info=$(vm_stat 2>/dev/null | perl -ne '/page size of (\d+)/ and $size=$1; /Pages\s+([^:]+)[^\d]+(\d+)/ and printf("%-20s % 16.2f Mi\n", "$1:", $2 * $size / 1048576);' 2>/dev/null || echo "Unable to fetch")
    local memory_free=$(echo "$memory_info" | grep "^free" | awk '{print $2, $3}' | head -1 || echo "N/A")
    local memory_active=$(echo "$memory_info" | grep "^active" | awk '{print $2, $3}' | head -1 || echo "N/A")

    local total_ram=$(sysctl -n hw.memsize 2>/dev/null | awk '{printf "%.1f Gi", $1/1073741824}' || echo "Unknown")

    local cpu_count=$(sysctl -n hw.ncpu 2>/dev/null || echo "Unknown")
    local cpu_brand=$(sysctl -n machdep.cpu.brand_string 2>/dev/null | sed 's/(R)//g;s/(TM)//g;s/  */ /g' || echo "Unknown")

    local load_avg=$(uptime | awk -F'load averages: ' '{print $2}' || echo "Unknown")

    local uptime_info=$(uptime | awk '{print $3, $4}' | sed 's/,//' || echo "Unknown")

    local xcode_path_raw=$(xcode-select -p 2>/dev/null || echo "Not Set")
    local xcode_path
    if [ "$xcode_path_raw" != "Not Set" ]; then
        # Extract the .app directory from the path
        # e.g., /Applications/Xcode16.2.app/Contents/Developer -> /Applications/Xcode16.2.app
        xcode_path=$(echo "$xcode_path_raw" | sed 's/\/Contents\/Developer$//')
    else
        xcode_path="Not Set"
    fi

    local machine_name=$(hostname)
    echo ""
    echo "✨  🔎 System Information for $machine_name"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    echo "── Core System ────────────────────────────────────────────────"
    printf "  📦 macOS Version:        %-15s Minimum:  %-15s %s\n" "$macos_version" "$EXPECTED_MACOS_VERSION" "$(compare_versions "$macos_version" "$EXPECTED_MACOS_VERSION" "minimum")"
    printf "  🖥  CPU:                  %s\n" "$cpu_brand"
    printf "  🧠 CPU Cores:            %s\n" "$cpu_count"
    printf "  💾 Total RAM:            %s\n" "$total_ram"
    printf "  ⏱  Uptime:               %s\n" "$uptime_info"
    printf "  📊 Load Average:         %s\n" "$load_avg"
    echo ""
    echo "── Development Tools ──────────────────────────────────────────"
    printf "  🛠  Xcode Version:        %-15s Expected: %-15s %s\n" "$xcode_version" "$EXPECTED_XCODE_VERSION" "$(compare_versions "$xcode_version" "$EXPECTED_XCODE_VERSION")"
    printf "  📂 Xcode Path:           %s\n" "$xcode_path"
    printf "  🌍 Node.js:              %-15s Expected: %-15s %s\n" "$node_version" "$EXPECTED_NODE_VERSION" "$(compare_versions "$node_version" "$EXPECTED_NODE_VERSION")"
    printf "  💎 Ruby:                 %-15s Expected: %-15s %s\n" "$ruby_version" "$EXPECTED_RUBY_VERSION" "$(compare_versions "$ruby_version" "$EXPECTED_RUBY_VERSION")"
    printf "  ☕ Java:                 %-15s Expected: %-15s %s\n" "$java_version" "$EXPECTED_JAVA_VERSION" "$(compare_versions "$java_version" "$EXPECTED_JAVA_VERSION")"
    printf "  🔧 Git:                  %s\n" "$git_version"
    echo ""
    echo "── React Native Environment ───────────────────────────────────"
    printf "  📦 Yarn:                 %s\n" "$yarn_version"
    printf "  📚 Bundler:              %s\n" "$bundler_version"
    echo ""
    echo "── Android Environment ────────────────────────────────────────"
    printf "  📱 SDK Version:          %-15s Expected: %-15s %s\n" "$android_sdk_installed" "$EXPECTED_ANDROID_SDK_VERSION" "$(compare_versions "$android_sdk_installed" "$EXPECTED_ANDROID_SDK_VERSION")"
    printf "  🔨 Build Tools:          %-15s Expected: %-15s %s\n" "$android_build_tools_installed" "$EXPECTED_ANDROID_BUILD_TOOLS_VERSION" "$(compare_versions "$android_build_tools_installed" "$EXPECTED_ANDROID_BUILD_TOOLS_VERSION")"
    printf "  🔧 NDK Version:          %-15s Expected: %-15s %s\n" "$android_ndk_installed" "$EXPECTED_ANDROID_NDK_VERSION" "$(compare_versions "$android_ndk_installed" "$EXPECTED_ANDROID_NDK_VERSION")"
    echo ""
    # Storage information
    local storage_info
    storage_info=$(df -h / | tail -1)
    local storage_total=$(echo "$storage_info" | awk '{print $2}')
    local storage_used=$(echo "$storage_info" | awk '{print $3}')
    local storage_available=$(echo "$storage_info" | awk '{print $4}')
    local storage_percent=$(echo "$storage_info" | awk '{print $5}')

    echo "── Storage & Memory ───────────────────────────────────────────"
    printf "  💾 Disk Total:           %s\n" "$storage_total"
    printf "  📊 Disk Used:            %s (%s)\n" "$storage_used" "$storage_percent"
    printf "  📂 Disk Available:       %s\n" "$storage_available"
    printf "  🧠 RAM Free:             %s\n" "$memory_free"
    printf "  🧠 RAM Active:           %s\n" "$memory_active"

    # Define ANSI color codes for pill tags
    local R=$'\e[0m'           # Reset
    local GREEN_FG=$'\e[32m'   # Green foreground
    local GREEN_BG=$'\e[42m'   # Green background
    local YELLOW_FG=$'\e[33m'  # Yellow foreground
    local YELLOW_BG=$'\e[43m'  # Yellow background
    local RED_FG=$'\e[31m'     # Red foreground
    local RED_BG=$'\e[41m'     # Red background
    local WHITE_FG=$'\e[97m'   # White foreground
    local BLACK_FG=$'\e[30m'   # Black foreground

    # Calculate disk health status
    local disk_percent_num=$(echo "$storage_percent" | sed 's/%//')
    local disk_status disk_pill
    if [ "$disk_percent_num" -lt 50 ]; then
        disk_status="HIGH"
        disk_pill="${R}${GREEN_FG}${GREEN_BG}${WHITE_FG} ${disk_status} ${R}${GREEN_FG}${R}"
    elif [ "$disk_percent_num" -lt 80 ]; then
        disk_status="MEDIUM"
        disk_pill="${R}${YELLOW_FG}${YELLOW_BG}${BLACK_FG} ${disk_status} ${R}${YELLOW_FG}${R}"
    else
        disk_status="LOW"
        disk_pill="${R}${RED_FG}${RED_BG}${WHITE_FG} ${disk_status} ${R}${RED_FG}${R}"
    fi

    # Calculate RAM status (free vs total)
    local memory_free_num=$(echo "$memory_free" | awk '{print $1}')
    local total_ram_num=$(echo "$total_ram" | sed 's/ Gi//' | awk '{printf "%.0f", $1 * 1024}')
    local ram_percent=$(awk "BEGIN {printf \"%.0f\", ($memory_free_num / $total_ram_num) * 100}")
    local ram_status ram_pill
    if [ "$ram_percent" -gt 25 ]; then
        ram_status="HIGH"
        ram_pill="${R}${GREEN_FG}${GREEN_BG}${WHITE_FG} ${ram_status} ${R}${GREEN_FG}${R}"
    elif [ "$ram_percent" -gt 10 ]; then
        ram_status="MEDIUM"
        ram_pill="${R}${YELLOW_FG}${YELLOW_BG}${BLACK_FG} ${ram_status} ${R}${YELLOW_FG}${R}"
    else
        ram_status="LOW"
        ram_pill="${R}${RED_FG}${RED_BG}${WHITE_FG} ${ram_status} ${R}${RED_FG}${R}"
    fi

    echo ""
    printf "  📊 Health Status:        Disk: %b   RAM: %b\n" "$disk_pill" "$ram_pill"
    echo ""

    echo "── Tool Manager Status ────────────────────────────────────────"
    printf "  📦 mise:                 %s\n" "$mise_version"
    printf "  🛠  Xcode CLI Tools:      %s\n" "$xcode_cli_version"
    echo ""

    echo "── iOS Runtimes & Simulators ──────────────────────────────────"
    echo "  📱 Available iOS Runtimes:"
    local runtimes_output
    runtimes_output=$(xcrun simctl list runtimes 2>/dev/null | grep iOS || true)
    if [ -z "$runtimes_output" ]; then
        echo "     ⚠️  No iOS runtimes found."
    else
        echo "$runtimes_output" | sed 's/^/     /'
    fi
    echo ""
    echo "  📲 Available Simulator Devices:"
    local sim_devices
    sim_devices=$(xcrun simctl list devices available 2>/dev/null | grep -E "iPhone|iPad" | grep -v "unavailable" | head -10 || true)
    if [ -z "$sim_devices" ]; then
        echo "     ⚠️  No simulator devices found."
    else
        echo "$sim_devices" | sed 's/^/     /'
        local total_sims=$(xcrun simctl list devices available 2>/dev/null | grep -E "iPhone|iPad" | grep -v "unavailable" | wc -l | tr -d ' ')
        if [ "$total_sims" -gt 10 ]; then
            echo "     ... and $((total_sims - 10)) more devices"
        fi
    fi
    echo ""

    if [ "${SIM_SUMMARY_JSON:-0}" = "1" ]; then
        echo "── JSON Summary ───────────────────────────────────────────────"
        local json
        json='{'
        json+="\"hostname\":\"$machine_name\","
        json+="\"macos\":\"$macos_version\","
        json+="\"xcode\":\"$xcode_version\","
        json+="\"xcodePath\":\"$xcode_path\","
        json+="\"androidSdk\":\"$android_sdk_installed\","
        json+="\"androidBuildTools\":\"$android_build_tools_installed\","
        json+="\"androidNdk\":\"$android_ndk_installed\","
        json+="\"node\":\"$node_version\","
        json+="\"ruby\":\"$ruby_version\","
        json+="\"java\":\"$java_version\","
        json+="\"git\":\"$git_version\","
        json+="\"yarn\":\"$yarn_version\","
        json+="\"bundler\":\"$bundler_version\","
        json+="\"cpuCores\":\"$cpu_count\","
        json+="\"totalRam\":\"$total_ram\","
        json+="\"loadAvg\":\"$load_avg\","
        json+="\"uptime\":\"$uptime_info\","
        json+="\"diskTotal\":\"$storage_total\","
        json+="\"diskUsed\":\"$storage_used\","
        json+="\"diskAvailable\":\"$storage_available\","
        json+="\"diskPercent\":\"$storage_percent\","
        json+="\"runtimes\":\"$(echo "$runtimes_output" | tr '"' "'" | tr '\n' ';')\""
        json+='}'
        echo "  $json"
        echo ""
    fi
    unset MACMINI_RUNNING || true
}

export_versions() {
    # Activate mise for tool version management
    if command -v mise >/dev/null 2>&1; then
        eval "$(mise activate bash)" >/dev/null 2>&1 || true
    fi

    # Detect versions (same logic as display_about, but output as sourceable variables)
    local xcode_version node_version ruby_version java_version
    local android_sdk_installed android_build_tools_installed android_ndk_version

    # Xcode (macOS only)
    if command -v xcodebuild >/dev/null 2>&1; then
        xcode_version=$(xcodebuild -version 2>/dev/null | grep 'Xcode' | sed 's/Xcode //' || echo "Not Installed")
    else
        xcode_version="Not Installed"
    fi

    # Node.js (managed by mise)
    if command -v node >/dev/null 2>&1; then
        node_version=$(node -v 2>/dev/null | sed 's/v//g' || echo "Not Installed")
    else
        node_version="Not Installed"
    fi

    # Ruby (managed by mise)
    if command -v ruby >/dev/null 2>&1; then
        ruby_version=$(ruby -v 2>/dev/null | awk '{print $2}' || echo "Not Installed")
    else
        ruby_version="Not Installed"
    fi

    # Java (managed by mise)
    if command -v java >/dev/null 2>&1; then
        java_version=$(java -version 2>&1 | head -n1 | awk -F'"' '{print $2}' || echo "Not Installed")
    else
        java_version="Not Installed"
    fi

    # Android SDK (Linux only)
    if command -v sdkmanager >/dev/null 2>&1; then
        android_sdk_installed=$(sdkmanager --list_installed 2>/dev/null | grep "platforms;android-" | awk -F';' '{print $2}' | sed 's/^android-//' | awk '{print $1}' | tr -d ' ')
        android_build_tools_installed=$(sdkmanager --list_installed 2>/dev/null | grep "build-tools;" | awk -F';' '{print $2}' | awk '{print $1}' | tr -d ' ')
        android_sdk_installed=${android_sdk_installed:-"Not Installed"}
        android_build_tools_installed=${android_build_tools_installed:-"Not Installed"}
        android_ndk_version=$(sdkmanager --list 2>/dev/null | grep -q "ndk;${EXPECTED_ANDROID_NDK_VERSION:-}" && echo "${EXPECTED_ANDROID_NDK_VERSION:-Not Installed}" || echo "Not Installed")
    else
        android_sdk_installed="Not Installed"
        android_build_tools_installed="Not Installed"
        android_ndk_version="Not Installed"
    fi

    # Output as sourceable shell variables
    echo "export DETECTED_XCODE_VERSION='$xcode_version'"
    echo "export DETECTED_NODE_VERSION='$node_version'"
    echo "export DETECTED_RUBY_VERSION='$ruby_version'"
    echo "export DETECTED_JAVA_VERSION='$java_version'"
    echo "export DETECTED_ANDROID_SDK_VERSION='$android_sdk_installed'"
    echo "export DETECTED_ANDROID_BUILD_TOOLS_VERSION='$android_build_tools_installed'"
    echo "export DETECTED_ANDROID_NDK_VERSION='$android_ndk_version'"
}

# ===================================================
# MAIN EXECUTION
# ===================================================

case "${1:-}" in
    init)
        # Remove system-wide RVM installation (we use mise instead)
        if [ -f /etc/profile.d/rvm.sh ]; then
            echo "🗑️  Removing system-wide RVM installation..."
            sudo mv /etc/profile.d/rvm.sh /etc/profile.d/rvm.sh.disabled || echo "⚠️  Could not disable RVM (may need sudo)"
            echo "✅ Disabled /etc/profile.d/rvm.sh"
        fi

        # Remove RVM from user directory
        if [ -d "$HOME/.rvm" ]; then
            echo "🗑️  Removing ~/.rvm directory..."
            mv "$HOME/.rvm" "$HOME/.rvm.backup.$(date +%s)" || echo "⚠️  Could not move ~/.rvm"
            echo "✅ Removed ~/.rvm"
        fi

        # Trust mise.toml BEFORE configuring .bashrc (which activates mise)
        if [ -f "$HOME/mise.toml" ] && command -v mise >/dev/null 2>&1; then
            echo "🔐 Trusting ~/mise.toml..."
            if ! mise trust ~/mise.toml; then
                echo "⚠️  Failed to trust ~/mise.toml (non-fatal, continuing...)"
            fi
        fi
        configure_bash_rc
        echo "✅ Mac Mini initialised! 🚀"
        ;;
    update)
        setup_environment
        echo "➡️  Updating tools and versions to match configuration..."
        ensure_macos_version || true
        install_required_tools || true
        install_mise_tools || true
        install_android_sdk || true
        install_xcode || true
        ensure_ios_runtime || true
        ensure_simulator_devices || true
        echo "✅ Update completed - all tools and versions up to date! 🚀"
        ;;
    clean)
        shift
        clean_machine "$@"
        ;;
    about)
        display_about
        ;;
    about:enforce)
        ensure_node_version
        ensure_ruby_version || true
        display_about
        ;;
    about:quick)
        echo "⚡ Quick About (no tool env sourcing)";
        sw_vers -productVersion || true;
        which node || true; node -v 2>/dev/null || true;
        which ruby || true; ruby -v 2>/dev/null || true;
        which java || true; java -version 2>&1 | head -n1 || true;
        exit 0
        ;;
    export-versions)
        export_versions
        ;;
    *)
        echo "Usage: $0 {init|update|clean|about|about:enforce|about:quick|export-versions}"
        exit 1
        ;;
 esac
