#!/bin/bash
set -euo pipefail

# Kill all child processes on Ctrl-C
trap 'printf "\n\033[31m  ✘\033[0m Interrupted — stopping all jobs...\n"; kill 0; exit 130' INT TERM

# ─── Configuration ────────────────────────────────────────────────────────────
# Override these via environment variables, a config file, or CLI argument.
#
# Config file format (shell):
#   SCHEME="MyAppScreenshots"
#   APP_BUNDLE_ID="com.example.myapp"
#   UITEST_BUNDLE_ID="com.example.myapp.UITests"
#   LANGUAGES=(en de fr)
#   DEVICE_MATRIX=(
#     "iPhone 17 Pro Max|26.4|iphone-17-pro-max|com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro-Max"
#   )
#   OUTPUT_DIR="Shots/Screenshots"

CONFIG_FILE="${1:-./screenshot.config}"
if [[ -f "$CONFIG_FILE" ]]; then
  # shellcheck source=/dev/null
  source "$CONFIG_FILE"
fi

# Required — must be set in config or environment
SCHEME="${SCHEME:?Set SCHEME in $CONFIG_FILE or environment}"
APP_BUNDLE_ID="${APP_BUNDLE_ID:?Set APP_BUNDLE_ID in $CONFIG_FILE or environment}"
UITEST_BUNDLE_ID="${UITEST_BUNDLE_ID:-}"

# Optional with defaults
OUTPUT_DIR="${OUTPUT_DIR:-Shots/Screenshots}"
DERIVED_DATA="${DERIVED_DATA:-DerivedData-Screenshots}"
RESET_SIMULATOR="${RESET_SIMULATOR:-1}"
PARALLEL="${PARALLEL:-1}"
VERBOSE="${VERBOSE:-0}"
STATUS_BAR_TIME="${STATUS_BAR_TIME:-9:41}"

if [[ -z "${LANGUAGES+x}" ]]; then
  LANGUAGES=(en)
fi

if [[ -z "${DEVICE_MATRIX+x}" ]]; then
  DEVICE_MATRIX=(
    "iPhone 17 Pro Max|26.4|iphone-17-pro-max|com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro-Max"
  )
fi

# ─── Pretty output ────────────────────────────────────────────────────────────
BOLD="\033[1m"
DIM="\033[2m"
GREEN="\033[32m"
RED="\033[31m"
CYAN="\033[36m"
RST="\033[0m"

ok()   { printf "${GREEN}  ✔${RST} %s\n" "$*"; }
fail() { printf "${RED}  ✘${RST} %s\n" "$*"; }
info() { printf "${CYAN}  ›${RST} %s\n" "$*"; }
step() { printf "\n${BOLD}%s${RST}\n" "$*"; }

is_truthy() {
  case "$1" in
    1|true|TRUE|yes|YES|on|ON) return 0 ;;
    *) return 1 ;;
  esac
}

# ─── Dependency check ─────────────────────────────────────────────────────────
command -v xcparse >/dev/null 2>&1 || {
  fail "xcparse not found. Install with: brew install chargepoint/xcparse/xcparse"
  exit 1
}

# ─── Simulator helpers ────────────────────────────────────────────────────────

resolve_udid() {
  local name="$1"; local os="$2"
  if [[ -n "$os" ]]; then
    xcrun simctl list devices | awk -v n="$name" -v o="$os" -F '[()]' '
      /^--.*--$/ { in_section = ($0 ~ o) }
      in_section && $0 ~ n { print $2; exit }
    '
  else
    xcrun simctl list devices | awk -v n="$name" -F '[()]' '
      $0 ~ n { print $2; exit }
    '
  fi
}

ensure_simulator() {
  local name="$1"; local runtime="$2"; local device_type="$3"
  local udid
  udid=$(resolve_udid "$name" "$runtime")
  if [[ -n "$udid" ]]; then
    echo "$udid"
    return 0
  fi

  local runtime_id
  runtime_id=$(xcrun simctl list runtimes | awk -v r="iOS $runtime" '$0 ~ r {for(i=1;i<=NF;i++) if($i ~ /com\.apple/) {print $i; exit}}')
  if [[ -z "$runtime_id" ]]; then
    fail "Runtime iOS $runtime not found" >&2
    return 1
  fi

  info "Creating simulator: $name (iOS $runtime)" >&2
  udid=$(xcrun simctl create "$name" "$device_type" "$runtime_id")
  echo "$udid"
}

prepare_simulator() {
  local udid="$1" lang="$2"
  local region
  region=$(echo "$lang" | tr '[:lower:]' '[:upper:]')

  xcrun simctl boot "$udid" 2>/dev/null || true

  # Language & locale
  xcrun simctl spawn "$udid" defaults write 'Apple Global Domain' AppleLanguages -array "$lang"
  xcrun simctl spawn "$udid" defaults write 'Apple Global Domain' AppleLocale "${lang}_${region}"

  # Suppress notifications
  xcrun simctl spawn "$udid" defaults write com.apple.springboard DoNotDisturb -bool true 2>/dev/null || true
  xcrun simctl spawn "$udid" defaults write com.apple.generativeexperiences.corefollowup \
    DateOfLastAppleIntelligenceReadinessCFU -date "2020-01-01T00:00:00Z" 2>/dev/null || true
  xcrun simctl spawn "$udid" defaults write com.apple.corefollow DisableFollowUp -bool true 2>/dev/null || true
  xcrun simctl spawn "$udid" defaults write com.apple.corefollowup DisableFollowUp -bool true 2>/dev/null || true

  # Reboot for language change
  xcrun simctl shutdown "$udid" 2>/dev/null || true
  xcrun simctl boot "$udid"

  # Clean status bar
  xcrun simctl status_bar "$udid" override \
    --time "$STATUS_BAR_TIME" \
    --batteryState charged --batteryLevel 100 \
    --wifiBars 3 \
    2>/dev/null || true
}

# ─── Build ────────────────────────────────────────────────────────────────────

build_for_testing() {
  local device_entry="$1"
  IFS='|' read -r dev_name dev_runtime dev_slug dev_type <<<"$device_entry"

  local udid
  udid=$(ensure_simulator "$dev_name" "$dev_runtime" "$dev_type")
  if [[ -z "$udid" ]]; then
    fail "Could not resolve or create simulator for $dev_name"; return 1
  fi

  info "Building $dev_name..."
  local log_file="/tmp/shooter-build-${dev_slug}.log"
  if xcodebuild build-for-testing \
    -scheme "$SCHEME" \
    -destination "id=$udid" \
    -derivedDataPath "$DERIVED_DATA" \
    -quiet \
    > "$log_file" 2>&1; then
    ok "Build succeeded ($dev_name)"
  else
    fail "Build failed ($dev_name)"
    cat "$log_file"
    return 1
  fi
}

# ─── Test one language ────────────────────────────────────────────────────────

run_one_language() {
  local device_entry="$1"
  local lang="$2"
  IFS='|' read -r dev_name dev_runtime dev_slug dev_type <<<"$device_entry"

  local label="${dev_slug}/${lang}"

  local udid
  udid=$(resolve_udid "$dev_name" "$dev_runtime")
  if [[ -z "$udid" ]]; then
    udid=$(ensure_simulator "$dev_name" "$dev_runtime" "$dev_type")
  fi
  if [[ -z "$udid" ]]; then
    fail "[$label] Could not resolve simulator"; return 1
  fi

  # Reset
  xcrun simctl shutdown "$udid" 2>/dev/null || true
  if is_truthy "$RESET_SIMULATOR"; then
    xcrun simctl erase "$udid"
  else
    for bundle in "$APP_BUNDLE_ID" ${UITEST_BUNDLE_ID:+"$UITEST_BUNDLE_ID"}; do
      xcrun simctl terminate "$udid" "$bundle" 2>/dev/null || true
      xcrun simctl uninstall "$udid" "$bundle" 2>/dev/null || true
    done
  fi

  udid=$(resolve_udid "$dev_name" "$dev_runtime")
  prepare_simulator "$udid" "$lang"

  local bundle="results-${dev_slug}-${lang}.xcresult"
  local outdir="${OUTPUT_DIR}/${dev_slug}/$lang"
  rm -rf "$bundle" "$outdir"
  mkdir -p "$outdir"

  local log_file="/tmp/shooter-test-${dev_slug}-${lang}.log"
  info "[$label] Testing..."

  local test_exit=0
  xcodebuild test-without-building \
    -scheme "$SCHEME" \
    -destination "id=$udid" \
    -derivedDataPath "$DERIVED_DATA" \
    -resultBundlePath "$bundle" \
    > "$log_file" 2>&1 || test_exit=$?

  if [[ $test_exit -eq 0 ]]; then
    xcparse screenshots "$bundle" "$outdir" > /dev/null 2>&1
    local count
    count=$(find "$outdir" -name '*.png' 2>/dev/null | wc -l | tr -d ' ')
    ok "[$label] ${count} screenshots"
  else
    fail "[$label] Tests failed"
    grep -E '(error:|FAIL|failed)' "$log_file" | head -20
    if is_truthy "$VERBOSE"; then
      printf "${DIM}"; cat "$log_file"; printf "${RST}"
    else
      printf "  ${DIM}Full log: $log_file${RST}\n"
    fi
  fi

  xcrun simctl shutdown "$udid" 2>/dev/null || true
  return $test_exit
}

# ─── Main ─────────────────────────────────────────────────────────────────────

step "Configuration"
info "Scheme:    $SCHEME"
info "Bundle ID: $APP_BUNDLE_ID"
info "Output:    $OUTPUT_DIR"
info "Languages: ${LANGUAGES[*]}"
info "Devices:   ${#DEVICE_MATRIX[@]}"

step "Building for testing"
for device_entry in "${DEVICE_MATRIX[@]}"; do
  build_for_testing "$device_entry"
done

step "Running screenshot tests"
total_runs=$((${#DEVICE_MATRIX[@]} * ${#LANGUAGES[@]}))
info "${#DEVICE_MATRIX[@]} devices × ${#LANGUAGES[@]} languages = ${total_runs} runs"

failed=0

if is_truthy "$PARALLEL"; then
  info "Devices run in parallel"
  pids=()
  for device_entry in "${DEVICE_MATRIX[@]}"; do
    (
      for lang in "${LANGUAGES[@]}"; do
        run_one_language "$device_entry" "$lang" || true
      done
    ) &
    pids+=($!)
  done
  for pid in "${pids[@]}"; do
    wait "$pid" || failed=$((failed + 1))
  done
else
  for device_entry in "${DEVICE_MATRIX[@]}"; do
    for lang in "${LANGUAGES[@]}"; do
      run_one_language "$device_entry" "$lang" || failed=$((failed + 1))
    done
  done
fi

# ─── Summary ──────────────────────────────────────────────────────────────────
step "Done"
total_screenshots=$(find "$OUTPUT_DIR" -name '*.png' 2>/dev/null | wc -l | tr -d ' ')
if [[ $failed -eq 0 ]]; then
  ok "All runs passed — ${total_screenshots} screenshots in ${OUTPUT_DIR}/"
else
  fail "${failed} run(s) had errors — ${total_screenshots} screenshots in ${OUTPUT_DIR}/"
  printf "  ${DIM}Re-run with VERBOSE=1 for full logs${RST}\n"
  exit 1
fi
