#!/usr/bin/env bash
# Configure Xcode preferences consistently across IDE, terminal, and CI.

set -euo pipefail

# -------- Colors (TTY-aware) --------
if [[ -t 1 ]]; then
  GREEN=$'\033[1;32m'; RED=$'\033[1;31m'; BLUE=$'\033[1;34m'; YELLOW=$'\033[1;33m'; NC=$'\033[0m'
else
  GREEN=""; RED=""; BLUE=""; YELLOW=""; NC=""
fi

# -------- Safety checks --------
if [[ "${EUID}" -eq 0 ]]; then
  echo "Please do not run as root; Xcode prefs are per-user." >&2
  exit 1
fi

# -------- Inputs & defaults --------
readonly REPO_ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../" && pwd)"
readonly DERIVED_DATA_PATH="${DERIVED_DATA_PATH:-$REPO_ROOT_DIR/DerivedData}"
readonly CLONED_SOURCE_PACKAGES_PATH="${CLONED_SOURCE_PACKAGES_PATH:-$REPO_ROOT_DIR/SourcePackages}"
readonly XCODE_DOMAIN="com.apple.dt.Xcode"
readonly XCODE_DEFAULTS_BACKUP_PATH="${HOME}/XcodeDefaults.backup.$(date +%Y%m%d%H%M%S).plist"

DRY_RUN="${DRY_RUN:-0}"

log() { echo -e "${*}"; }

# -------- Helpers --------
function read_pref() {
  local key="$1"
  defaults read "${XCODE_DOMAIN}" "${key}" 2>/dev/null || true
}

function write_pref_typed() {
  local key="$1"; local type="$2"; local value="$3"
  if [[ "$DRY_RUN" == "1" ]]; then
    log "${BLUE}${key}${NC}: (dry-run) would set ${type} => ${GREEN}${value}${NC}"
    return 0
  fi
  defaults write "${XCODE_DOMAIN}" "${key}" "-${type}" "${value}"
}

function save_pref() {
  # save_pref <key> <value> <type>
  # type: bool|string|int
  local key="$1"; local new_val="$2"; local type="$3"

  local prev_val; prev_val="$(read_pref "${key}")"
  if [[ "${prev_val}" == "${new_val}" ]]; then
    log "${BLUE}${key}${NC}: ${GREEN}${new_val}${NC} (unchanged)"
    return 0
  fi

  log "${BLUE}${key}${NC}: ${GREEN}${new_val}${NC} (was '${prev_val}')"
  case "$type" in
    bool) write_pref_typed "${key}" bool "${new_val}" ;;
    int)  write_pref_typed "${key}" int  "${new_val}" ;;
    *)    write_pref_typed "${key}" string "${new_val}" ;;
  esac

  # verify
  local after; after="$(read_pref "${key}")"
  if [[ "${after}" != "${new_val}" ]]; then
    log "${YELLOW}Warning:${NC} wrote '${new_val}' to ${key}, but read-back is '${after}'. Key may be unknown in this Xcode version."
  fi
}

function backup_prefs() {
  [[ -n "${CI:-}" ]] && return 0
  log "\nCreating backup of current Xcode preferences..."
  mkdir -p "$(dirname "${XCODE_DEFAULTS_BACKUP_PATH}")"
  # tolerate missing domain
  if defaults read "${XCODE_DOMAIN}" > "${XCODE_DEFAULTS_BACKUP_PATH}" 2>/dev/null; then
    log "✅ Backup created: ${BLUE}${XCODE_DEFAULTS_BACKUP_PATH}${NC}"
  else
    echo "{}" > "${XCODE_DEFAULTS_BACKUP_PATH}"
    log "ℹ️  No existing domain; wrote empty backup to ${BLUE}${XCODE_DEFAULTS_BACKUP_PATH}${NC}"
  fi
}

function update_prefs() {
  log "\nUpdating Xcode preferences..."
  # Ensure repo-local DerivedData & SourcePackages (keep them .gitignored)
  mkdir -p "${DERIVED_DATA_PATH}" "${CLONED_SOURCE_PACKAGES_PATH}"
  save_pref "IDECustomDerivedDataLocation" "${DERIVED_DATA_PATH}" string
  save_pref "IDEClonedSourcePackagesDirPathOverride" "${CLONED_SOURCE_PACKAGES_PATH}" string

  # Skip validations (speeds up Swift Package plugin/macro scenarios)
  # NOTE: spelling is intentional per Xcode internals.
  save_pref "IDESkipPackagePluginFingerprintValidatation" "YES" bool
  save_pref "IDESkipMacroFingerprintValidation" "YES" bool

  # Build/UX prefs (non-fatal if keys disappear in newer Xcode)
  save_pref "EnableSwiftBuildSystemIntegration" "1" int
  save_pref "ShowBuildOperationDuration" "YES" bool
  save_pref "IDEIndexerActivityShowNumericProgress" "YES" bool
  save_pref "IDEPackageEnablePrebuilts" "1" int

  log "✅ Xcode preferences updated. Restart Xcode for changes to apply."
}

# -------- Run --------
backup_prefs
update_prefs
