#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  scripts/android-screenshots.sh [--form-factor all|phone|wear] [--device <adb-serial>] [--avd <name>] [--locale en-US] [--skip-build] [--skip-install] [--keep-emulator] [--dry-run]

Builds and installs the phone and Wear OS debug apps on matching emulators,
launches production screens with deterministic local fixture state, and writes
Google Play screenshots under:
  apps/android/fastlane/metadata/android/<locale>/images/phoneScreenshots/
  apps/android/fastlane/metadata/android/<locale>/images/wearScreenshots/

Capture evidence is saved under:
  .artifacts/android-screenshots/latest/

By default, the script captures both form factors using retained Pixel 2 and
Wear OS Large Round AVDs. Use --form-factor with --avd or --device to capture
one form factor on an explicitly selected emulator.
EOF
}

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ANDROID_DIR="${ROOT_DIR}/apps/android"
DEFAULT_SCREENSHOT_AVD="OpenClaw_Screenshots_API36"
DEFAULT_SCREENSHOT_DEVICE_PROFILE="pixel_2"
DEFAULT_WEAR_SCREENSHOT_AVD="OpenClaw_Wear_Screenshots_API34"
DEFAULT_WEAR_SCREENSHOT_DEVICE_PROFILE="wearos_large_round"
case "$(uname -m)" in
  arm64|aarch64) DEFAULT_SCREENSHOT_ABI="arm64-v8a" ;;
  *) DEFAULT_SCREENSHOT_ABI="x86_64" ;;
esac
DEFAULT_SCREENSHOT_SYSTEM_IMAGE="system-images;android-36;google_apis;${DEFAULT_SCREENSHOT_ABI}"
DEFAULT_WEAR_SCREENSHOT_SYSTEM_IMAGE="system-images;android-34;android-wear;${DEFAULT_SCREENSHOT_ABI}"
FORM_FACTOR="${ANDROID_SCREENSHOT_FORM_FACTOR:-all}"
LOCALE="en-US"
DEVICE="${ANDROID_SCREENSHOT_DEVICE:-}"
AVD="${ANDROID_SCREENSHOT_AVD:-$DEFAULT_SCREENSHOT_AVD}"
SCREENSHOT_DEVICE_PROFILE="${ANDROID_SCREENSHOT_DEVICE_PROFILE:-$DEFAULT_SCREENSHOT_DEVICE_PROFILE}"
SCREENSHOT_SYSTEM_IMAGE="${ANDROID_SCREENSHOT_SYSTEM_IMAGE:-$DEFAULT_SCREENSHOT_SYSTEM_IMAGE}"
KEEP_EMULATOR="${ANDROID_SCREENSHOT_KEEP_EMULATOR:-0}"
SKIP_BUILD=0
SKIP_INSTALL=0
DRY_RUN=0
SCENES=(home chat settings gateway voice-wake)
OUTPUT_TYPE="phoneScreenshots"
GRADLE_ASSEMBLE_TASK=":app:assemblePlayDebug"
ACTIVITY_COMPONENT="ai.openclaw.app/.MainActivity"
EMULATOR_PID=""
EMULATOR_LOG=""
STARTED_EMULATOR=0
ARTIFACT_ROOT="${ROOT_DIR}/.artifacts/android-screenshots/latest"
ARTIFACT_DIR="${ARTIFACT_ROOT}/phone"
SCREENSHOT_SIZE="${ANDROID_SCREENSHOT_SIZE:-1440x2560}"
DISPLAY_OVERRIDDEN=0
ORIGINAL_WM_SIZE=""
ORIGINAL_WM_DENSITY=""
SCREENSHOT_DENSITY=""
TIMEZONE_OVERRIDDEN=0
ORIGINAL_AUTO_TIME_ZONE=""
ORIGINAL_TIME_ZONE=""
DEVICE_EXPLICIT=0
AVD_EXPLICIT=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --)
      shift
      ;;
    --form-factor)
      FORM_FACTOR="${2:-}"
      shift 2
      ;;
    --device)
      DEVICE="${2:-}"
      DEVICE_EXPLICIT=1
      shift 2
      ;;
    --avd)
      AVD="${2:-}"
      AVD_EXPLICIT=1
      shift 2
      ;;
    --locale)
      LOCALE="${2:-}"
      shift 2
      ;;
    --skip-build)
      SKIP_BUILD=1
      shift
      ;;
    --skip-install)
      SKIP_INSTALL=1
      shift
      ;;
    --keep-emulator)
      KEEP_EMULATOR=1
      shift
      ;;
    --dry-run)
      DRY_RUN=1
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      usage
      exit 1
      ;;
  esac
done

case "$FORM_FACTOR" in
  all)
    if [[ "$DEVICE_EXPLICIT" == "1" || "$AVD_EXPLICIT" == "1" ]]; then
      echo "--device and --avd require --form-factor phone or --form-factor wear." >&2
      exit 1
    fi
    if [[ "$KEEP_EMULATOR" == "1" ]]; then
      echo "--keep-emulator requires --form-factor phone or --form-factor wear." >&2
      exit 1
    fi
    child_args=(--locale "$LOCALE")
    [[ "$SKIP_BUILD" == "1" ]] && child_args+=(--skip-build)
    [[ "$SKIP_INSTALL" == "1" ]] && child_args+=(--skip-install)
    [[ "$DRY_RUN" == "1" ]] && child_args+=(--dry-run)
    bash "$0" --form-factor phone "${child_args[@]}"
    bash "$0" --form-factor wear "${child_args[@]}"
    exit 0
    ;;
  phone)
    ;;
  wear)
    if [[ "$DEVICE_EXPLICIT" != "1" ]]; then
      DEVICE="${ANDROID_WEAR_SCREENSHOT_DEVICE:-}"
    fi
    if [[ "$AVD_EXPLICIT" != "1" ]]; then
      AVD="${ANDROID_WEAR_SCREENSHOT_AVD:-$DEFAULT_WEAR_SCREENSHOT_AVD}"
    fi
    SCREENSHOT_DEVICE_PROFILE="${ANDROID_WEAR_SCREENSHOT_DEVICE_PROFILE:-$DEFAULT_WEAR_SCREENSHOT_DEVICE_PROFILE}"
    SCREENSHOT_SYSTEM_IMAGE="${ANDROID_WEAR_SCREENSHOT_SYSTEM_IMAGE:-$DEFAULT_WEAR_SCREENSHOT_SYSTEM_IMAGE}"
    SCREENSHOT_SIZE="${ANDROID_WEAR_SCREENSHOT_SIZE:-454x454}"
    SCENES=(chat voice controls)
    OUTPUT_TYPE="wearScreenshots"
    GRADLE_ASSEMBLE_TASK=":wear:assembleDebug"
    ACTIVITY_COMPONENT="ai.openclaw.app/ai.openclaw.wear.MainActivity"
    ARTIFACT_DIR="${ARTIFACT_ROOT}/wear"
    ;;
  *)
    echo "Invalid Android screenshot form factor: ${FORM_FACTOR}" >&2
    echo "Use all, phone, or wear." >&2
    exit 1
    ;;
esac

validate_locale() {
  local locale="$1"
  if [[ "$locale" =~ ^[A-Za-z0-9][A-Za-z0-9_-]*$ ]]; then
    return
  fi
  echo "Invalid Android screenshot locale: ${locale}" >&2
  echo "Use a locale tag like en-US or pt-BR; path separators and dot segments are not allowed." >&2
  exit 1
}

validate_locale "$LOCALE"

if [[ ! "$SCREENSHOT_SIZE" =~ ^[0-9]+x[0-9]+$ ]]; then
  echo "Invalid Android screenshot size: ${SCREENSHOT_SIZE}" >&2
  echo "Use a pixel size like 1080x1920." >&2
  exit 1
fi
SCREENSHOT_WIDTH=$((10#${SCREENSHOT_SIZE%x*}))
SCREENSHOT_HEIGHT=$((10#${SCREENSHOT_SIZE#*x}))
SCREENSHOT_MIN_DIMENSION=$((SCREENSHOT_WIDTH < SCREENSHOT_HEIGHT ? SCREENSHOT_WIDTH : SCREENSHOT_HEIGHT))
SCREENSHOT_MAX_DIMENSION=$((SCREENSHOT_WIDTH > SCREENSHOT_HEIGHT ? SCREENSHOT_WIDTH : SCREENSHOT_HEIGHT))
if (( SCREENSHOT_MIN_DIMENSION < 320 || SCREENSHOT_MAX_DIMENSION > 3840 || SCREENSHOT_MAX_DIMENSION > SCREENSHOT_MIN_DIMENSION * 2 )); then
  echo "Android screenshot size ${SCREENSHOT_SIZE} does not meet Google Play dimension and aspect-ratio limits." >&2
  exit 1
fi

cleanup_started_emulator() {
  local stopped=0

  if [[ "$STARTED_EMULATOR" != "1" || "$KEEP_EMULATOR" == "1" ]]; then
    return
  fi
  if [[ -n "${ADB_BIN:-}" && -n "${ADB_SERIAL:-}" ]]; then
    if "$ADB_BIN" -s "$ADB_SERIAL" emu kill >/dev/null 2>&1; then
      stopped=1
      local deadline=$((SECONDS + 30))
      while (( SECONDS < deadline )); do
        if ! "$ADB_BIN" devices | awk 'NR > 1 && $2 == "device" { print $1 }' | grep -Fxq "$ADB_SERIAL"; then
          break
        fi
        sleep 1
      done
    fi
  fi
  if [[ "$stopped" != "1" && -n "$EMULATOR_PID" ]]; then
    kill "$EMULATOR_PID" >/dev/null 2>&1 || true
  fi
}

restore_device_display() {
  if [[ "$DISPLAY_OVERRIDDEN" != "1" || -z "${ADB_BIN:-}" || -z "${ADB_SERIAL:-}" ]]; then
    return
  fi
  if [[ -n "$ORIGINAL_WM_SIZE" ]]; then
    "$ADB_BIN" -s "$ADB_SERIAL" shell wm size "$ORIGINAL_WM_SIZE" >/dev/null 2>&1 || true
  else
    "$ADB_BIN" -s "$ADB_SERIAL" shell wm size reset >/dev/null 2>&1 || true
  fi
  if [[ -n "$ORIGINAL_WM_DENSITY" ]]; then
    "$ADB_BIN" -s "$ADB_SERIAL" shell wm density "$ORIGINAL_WM_DENSITY" >/dev/null 2>&1 || true
  else
    "$ADB_BIN" -s "$ADB_SERIAL" shell wm density reset >/dev/null 2>&1 || true
  fi
}

restore_device_timezone() {
  if [[ "$TIMEZONE_OVERRIDDEN" != "1" || -z "${ADB_BIN:-}" || -z "${ADB_SERIAL:-}" ]]; then
    return
  fi
  if [[ -n "$ORIGINAL_TIME_ZONE" ]]; then
    "$ADB_BIN" -s "$ADB_SERIAL" shell cmd alarm set-timezone "$ORIGINAL_TIME_ZONE" >/dev/null 2>&1 || true
  fi
  if [[ "$ORIGINAL_AUTO_TIME_ZONE" == "true" || "$ORIGINAL_AUTO_TIME_ZONE" == "false" ]]; then
    "$ADB_BIN" -s "$ADB_SERIAL" shell cmd time_zone_detector set_auto_detection_enabled "$ORIGINAL_AUTO_TIME_ZONE" >/dev/null 2>&1 || true
  fi
}

cleanup_emulator_log() {
  if [[ -n "$EMULATOR_LOG" && -f "$EMULATOR_LOG" ]]; then
    rm -f "$EMULATOR_LOG"
  fi
}

cleanup() {
  restore_device_display
  restore_device_timezone
  cleanup_started_emulator
  cleanup_emulator_log
}

trap cleanup EXIT

adb_bin() {
  if [[ -n "${ADB:-}" ]]; then
    printf '%s\n' "$ADB"
    return
  fi
  if command -v adb >/dev/null 2>&1; then
    command -v adb
    return
  fi
  for sdk_root in "${ANDROID_HOME:-}" "${ANDROID_SDK_ROOT:-}" "$HOME/Library/Android/sdk"; do
    if [[ -n "$sdk_root" && -x "$sdk_root/platform-tools/adb" ]]; then
      printf '%s\n' "$sdk_root/platform-tools/adb"
      return
    fi
  done
  echo "adb not found. Install Android platform-tools or set ADB." >&2
  return 127
}

emulator_bin() {
  if [[ -n "${ANDROID_EMULATOR:-}" ]]; then
    printf '%s\n' "$ANDROID_EMULATOR"
    return
  fi
  if command -v emulator >/dev/null 2>&1; then
    command -v emulator
    return
  fi
  for sdk_root in "${ANDROID_HOME:-}" "${ANDROID_SDK_ROOT:-}" "$HOME/Library/Android/sdk"; do
    if [[ -n "$sdk_root" && -x "$sdk_root/emulator/emulator" ]]; then
      printf '%s\n' "$sdk_root/emulator/emulator"
      return
    fi
  done
  echo "Android emulator binary not found. Install the Android emulator or set ANDROID_EMULATOR." >&2
  return 127
}

avdmanager_bin() {
  if [[ -n "${AVDMANAGER:-}" ]]; then
    printf '%s\n' "$AVDMANAGER"
    return
  fi
  if command -v avdmanager >/dev/null 2>&1; then
    command -v avdmanager
    return
  fi
  for sdk_root in "${ANDROID_HOME:-}" "${ANDROID_SDK_ROOT:-}" "$HOME/Library/Android/sdk"; do
    for relative_path in cmdline-tools/latest/bin/avdmanager cmdline-tools/bin/avdmanager tools/bin/avdmanager; do
      if [[ -n "$sdk_root" && -x "$sdk_root/$relative_path" ]]; then
        printf '%s\n' "$sdk_root/$relative_path"
        return
      fi
    done
  done
  echo "avdmanager not found. Install Android SDK command-line tools or set AVDMANAGER." >&2
  return 127
}

ensure_screenshot_avd() {
  local avd="$1"
  local emulator
  local avdmanager

  emulator="$(emulator_bin)"
  if "$emulator" -list-avds | grep -Fxq "$avd"; then
    return
  fi

  avdmanager="$(avdmanager_bin)"
  echo "Creating no-cutout screenshot AVD '${avd}' from device profile '${SCREENSHOT_DEVICE_PROFILE}'." >&2
  if ! printf 'no\n' | "$avdmanager" create avd \
    --force \
    --name "$avd" \
    --package "$SCREENSHOT_SYSTEM_IMAGE" \
    --device "$SCREENSHOT_DEVICE_PROFILE"; then
    echo "Could not create Android screenshot AVD '${avd}'." >&2
    echo "Install SDK package '${SCREENSHOT_SYSTEM_IMAGE}' or set ANDROID_SCREENSHOT_SYSTEM_IMAGE." >&2
    return 1
  fi
}

connected_devices() {
  local adb="$1"
  "$adb" devices | awk 'NR > 1 && $2 == "device" { print $1 }'
}

device_count() {
  local devices="$1"
  printf '%s\n' "$devices" | sed '/^$/d' | wc -l | tr -d ' '
}

running_avd_name() {
  local adb="$1"
  local serial="$2"
  "$adb" -s "$serial" emu avd name 2>/dev/null | tr -d '\r' | sed -n '1p'
}

wait_for_single_device() {
  local adb="$1"
  local timeout_seconds="${ANDROID_SCREENSHOT_EMULATOR_TIMEOUT_SECONDS:-180}"
  local deadline=$((SECONDS + timeout_seconds))
  local devices
  local count

  while (( SECONDS < deadline )); do
    devices="$(connected_devices "$adb")"
    count="$(device_count "$devices")"
    if [[ "$count" == "1" ]]; then
      printf '%s\n' "$devices"
      return
    fi
    sleep 2
  done

  echo "Timed out waiting for exactly one Android emulator device." >&2
  "$adb" devices -l >&2 || true
  return 1
}

wait_for_boot_completed() {
  local adb="$1"
  local serial="$2"
  local timeout_seconds="${ANDROID_SCREENSHOT_EMULATOR_TIMEOUT_SECONDS:-180}"
  local deadline=$((SECONDS + timeout_seconds))
  local boot_completed

  "$adb" -s "$serial" wait-for-device
  while (( SECONDS < deadline )); do
    boot_completed="$("$adb" -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true)"
    if [[ "$boot_completed" == "1" ]]; then
      "$adb" -s "$serial" shell input keyevent 82 >/dev/null 2>&1 || true
      return
    fi
    sleep 2
  done

  echo "Timed out waiting for Android emulator boot completion on ${serial}." >&2
  return 1
}

wait_for_explicit_device() {
  local adb="$1"
  local serial="$2"
  local timeout_seconds="${ANDROID_SCREENSHOT_DEVICE_TIMEOUT_SECONDS:-30}"
  local deadline=$((SECONDS + timeout_seconds))
  local state

  while (( SECONDS < deadline )); do
    state="$("$adb" devices | awk -v serial="$serial" '$1 == serial { print $2 }')"
    if [[ "$state" == "device" ]]; then
      return
    fi
    sleep 2
  done

  if [[ -n "$state" ]]; then
    echo "Android device '${serial}' did not become usable within ${timeout_seconds}s; current adb state is '${state}'." >&2
  else
    echo "Android device '${serial}' was not found within ${timeout_seconds}s." >&2
  fi
  "$adb" devices -l >&2 || true
  return 1
}

stabilize_device_for_screenshots() {
  local adb="$1"
  local serial="$2"
  ORIGINAL_AUTO_TIME_ZONE="$("$adb" -s "$serial" shell cmd time_zone_detector is_auto_detection_enabled 2>/dev/null | tr -d '\r')"
  ORIGINAL_TIME_ZONE="$("$adb" -s "$serial" shell getprop persist.sys.timezone 2>/dev/null | tr -d '\r')"
  if [[ "$ORIGINAL_AUTO_TIME_ZONE" != "true" && "$ORIGINAL_AUTO_TIME_ZONE" != "false" ]]; then
    echo "Could not determine emulator automatic timezone setting." >&2
    return 1
  fi
  if [[ -z "$ORIGINAL_TIME_ZONE" ]]; then
    echo "Could not determine emulator timezone." >&2
    return 1
  fi
  # Arm cleanup before the first mutation; restoring an unchanged snapshot is safe.
  TIMEZONE_OVERRIDDEN=1
  # Seeded chat timestamps use the device timezone, so disable detection before
  # pinning UTC to avoid inheriting the runner's locale.
  "$adb" -s "$serial" shell cmd time_zone_detector set_auto_detection_enabled false >/dev/null
  "$adb" -s "$serial" shell cmd alarm set-timezone UTC >/dev/null
  "$adb" -s "$serial" shell settings put global window_animation_scale 0 >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell settings put global transition_animation_scale 0 >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell settings put global animator_duration_scale 0 >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell settings put global stay_on_while_plugged_in 3 >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell svc power stayon true >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell input keyevent 224 >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell wm dismiss-keyguard >/dev/null 2>&1 || true
  "$adb" -s "$serial" shell settings put system font_scale 1.0 >/dev/null 2>&1 || true
}

require_emulator_device() {
  local adb="$1"
  local serial="$2"
  local qemu

  qemu="$("$adb" -s "$serial" shell getprop ro.kernel.qemu 2>/dev/null | tr -d '\r')"
  if [[ "$qemu" == "1" ]]; then
    return
  fi
  echo "Android screenshot capture requires an emulator; '${serial}' is not an emulator." >&2
  echo "Pass --avd <name> or --device <emulator-serial>." >&2
  return 1
}

configure_screenshot_display() {
  local adb="$1"
  local serial="$2"
  local current_size
  local current_density
  local effective_size
  local effective_density
  local effective_width

  current_size="$("$adb" -s "$serial" shell wm size 2>/dev/null | tr -d '\r')"
  current_density="$("$adb" -s "$serial" shell wm density 2>/dev/null | tr -d '\r')"
  ORIGINAL_WM_SIZE="$(printf '%s\n' "$current_size" | sed -n 's/^Override size: //p')"
  ORIGINAL_WM_DENSITY="$(printf '%s\n' "$current_density" | sed -n 's/^Override density: //p')"
  effective_size="${ORIGINAL_WM_SIZE:-$(printf '%s\n' "$current_size" | sed -n 's/^Physical size: //p')}"
  effective_density="${ORIGINAL_WM_DENSITY:-$(printf '%s\n' "$current_density" | sed -n 's/^Physical density: //p')}"
  if [[ ! "$effective_size" =~ ^[0-9]+x[0-9]+$ || ! "$effective_density" =~ ^[0-9]+$ ]]; then
    echo "Could not determine emulator display size and density." >&2
    return 1
  fi

  effective_width=$((10#${effective_size%x*}))
  SCREENSHOT_DENSITY=$(((10#$effective_density * SCREENSHOT_WIDTH + effective_width / 2) / effective_width))
  DISPLAY_OVERRIDDEN=1
  "$adb" -s "$serial" shell wm size "$SCREENSHOT_SIZE" >/dev/null
  "$adb" -s "$serial" shell wm density "$SCREENSHOT_DENSITY" >/dev/null
  echo "Android screenshot density: ${SCREENSHOT_DENSITY} dpi"
}

boot_emulator() {
  local adb="$1"
  local avd="$2"
  local emulator
  local emulator_args
  local extra_args
  local serial

  ensure_screenshot_avd "$avd"
  emulator="$(emulator_bin)"
  EMULATOR_LOG="$(mktemp "${TMPDIR:-/tmp}/openclaw-android-screenshot-emulator.XXXXXX.log")"
  echo "No connected Android device found. Booting AVD '${avd}'." >&2
  emulator_args=(-avd "$avd" -no-window -no-audio -no-boot-anim)
  if [[ -n "${ANDROID_SCREENSHOT_EMULATOR_ARGS:-}" ]]; then
    read -r -a extra_args <<<"$ANDROID_SCREENSHOT_EMULATOR_ARGS"
    emulator_args+=("${extra_args[@]}")
  fi
  "$emulator" "${emulator_args[@]}" >"$EMULATOR_LOG" 2>&1 &
  EMULATOR_PID="$!"
  STARTED_EMULATOR=1

  serial="$(wait_for_single_device "$adb")"
  wait_for_boot_completed "$adb" "$serial"
  ADB_SERIAL="$serial"
}

resolve_device() {
  local adb="$1"
  local devices
  local count
  local connected_avd

  if [[ -n "$DEVICE" ]]; then
    wait_for_explicit_device "$adb" "$DEVICE"
    ADB_SERIAL="$DEVICE"
    return
  fi
  devices="$(connected_devices "$adb")"
  count="$(device_count "$devices")"
  if [[ "$count" == "1" ]]; then
    connected_avd="$(running_avd_name "$adb" "$devices")"
    if [[ "$connected_avd" != "$AVD" ]]; then
      echo "Connected emulator '${connected_avd:-unknown}' is not the screenshot AVD '${AVD}'." >&2
      echo "Stop it so the script can boot '${AVD}', or pass --device '${devices}' to override the no-cutout profile." >&2
      return 1
    fi
    ADB_SERIAL="$devices"
    return
  fi
  if [[ "$count" == "0" ]]; then
    boot_emulator "$adb" "$AVD"
    return
  else
    echo "Multiple Android devices are connected. Pass --device <adb-serial>." >&2
  fi
  return 1
}

latest_debug_apk() {
  local output_dir
  local pattern

  if [[ "$FORM_FACTOR" == "wear" ]]; then
    output_dir="${ANDROID_DIR}/wear/build/outputs/apk/debug"
    pattern='*-debug.apk'
  else
    output_dir="${ANDROID_DIR}/app/build/outputs/apk/play/debug"
    pattern='*-play-debug.apk'
  fi
  if [[ ! -d "$output_dir" ]]; then
    return 0
  fi
  find "$output_dir" -maxdepth 1 -name "$pattern" -print 2>/dev/null | sort | tail -n 1
}

scene_ready_text() {
  if [[ "$FORM_FACTOR" == "wear" ]]; then
    case "$1" in
      chat) printf '%s\n' "Release planning" ;;
      voice) printf '%s\n' "Dictate" ;;
      controls) printf '%s\n' "Gateway connected" ;;
      *)
        echo "Unknown Wear OS screenshot scene: $1" >&2
        return 1
        ;;
    esac
    return
  fi
  case "$1" in
    home) printf '%s\n' "Overview" ;;
    # The screenshot fixture seeds chat history and restores at the latest user
    # turn, so wait for that visible anchor instead of empty-chat copy.
    chat) printf '%s\n' "Draft a short status update for the team." ;;
    settings) printf '%s\n' "OpenClaw mobile" ;;
    voice-wake) printf '%s\n' "Wake listener" ;;
    # Connected fixtures can push Add Gateway below the composed viewport, so
    # wait for the gateway detail's always-visible subtitle instead.
    gateway) printf '%s\n' "Connection between this phone and OpenClaw." ;;
    *)
      echo "Unknown Android screenshot scene: $1" >&2
      return 1
      ;;
  esac
}

wait_for_scene_ready() {
  local adb="$1"
  local serial="$2"
  local scene="$3"
  local dump_path="$4"
  local marker
  local timeout_seconds="${ANDROID_SCREENSHOT_SCENE_TIMEOUT_SECONDS:-45}"
  local deadline=$((SECONDS + timeout_seconds))

  marker="$(scene_ready_text "$scene")"
  while (( SECONDS < deadline )); do
    if "$adb" -s "$serial" exec-out uiautomator dump /dev/tty >"$dump_path" 2>/dev/null; then
      # A newly created Wear AVD may cover the resumed app with its charging
      # overlay after stay-awake is enabled. Dismiss it or first-run capture stalls.
      if [[ "$FORM_FACTOR" == "wear" ]] && grep -Fq 'com.google.android.wearable.sysui:id/charging_container' "$dump_path"; then
        "$adb" -s "$serial" shell input keyevent 4 >/dev/null 2>&1 || true
        sleep 0.5
        continue
      fi
      if grep -Fq "$marker" "$dump_path"; then
        return
      fi
    fi
    sleep 1
  done

  echo "Timed out waiting for scene '${scene}' to expose '${marker}' in the Android UI tree." >&2
  return 1
}

sips_bin() {
  if [[ -n "${SIPS:-}" ]]; then
    printf '%s\n' "$SIPS"
    return
  fi
  if command -v sips >/dev/null 2>&1; then
    command -v sips
    return
  fi
  echo "sips not found. Android release screenshots require macOS or an explicit SIPS executable." >&2
  return 127
}

normalize_capture_for_play() {
  local input_path="$1"
  local output_path="$2"
  local sips
  local description

  sips="$(sips_bin)"
  "$sips" -s format jpeg -s formatOptions best "$input_path" --out "$output_path" >/dev/null
  rm -f "$input_path"

  description="$(file "$output_path")"
  if [[ "$description" != *"${SCREENSHOT_SIZE/x/x}"* || "$description" != *"JPEG image data"* ]]; then
    echo "Invalid Google Play screenshot output: ${description}" >&2
    return 1
  fi
}

write_artifact_manifest() {
  local serial="$1"
  local avd_name
  local git_sha
  local checksum_command

  avd_name="$(running_avd_name "$ADB_BIN" "$serial")"
  git_sha="$(git -C "$ROOT_DIR" rev-parse HEAD)"
  if command -v shasum >/dev/null 2>&1; then
    checksum_command=(shasum -a 256)
  else
    checksum_command=(sha256sum)
  fi

  {
    printf 'git_sha=%s\n' "$git_sha"
    printf 'form_factor=%s\n' "$FORM_FACTOR"
    printf 'output_type=%s\n' "$OUTPUT_TYPE"
    printf 'device=%s\n' "$serial"
    printf 'avd=%s\n' "${avd_name:-unknown}"
    printf 'locale=%s\n' "$LOCALE"
    printf 'size=%s\n' "$SCREENSHOT_SIZE"
    printf 'density=%s\n' "$SCREENSHOT_DENSITY"
    printf 'format=high-quality JPEG\n'
    printf 'scenes=%s\n' "${SCENES[*]}"
    printf 'screenshots:\n'
    "${checksum_command[@]}" "$ARTIFACT_DIR"/screenshots/*.jpg
  } >"$ARTIFACT_DIR/manifest.txt"
}

OUTPUT_DIR="${ANDROID_DIR}/fastlane/metadata/android/${LOCALE}/images/${OUTPUT_TYPE}"
ADB_SERIAL=""
ADB_DISPLAY="${DEVICE:-<auto>}"

echo "Android screenshot output: ${OUTPUT_DIR}"
echo "Android screenshot artifacts: ${ARTIFACT_DIR}"
echo "Android screenshot form factor: ${FORM_FACTOR}"
echo "Android screenshot size: ${SCREENSHOT_SIZE}"
echo "Scenes: ${SCENES[*]}"
echo "ADB device: ${ADB_DISPLAY}"
echo "Screenshot AVD: ${AVD}"
echo "Screenshot device profile: ${SCREENSHOT_DEVICE_PROFILE}"
echo "Screenshot system image: ${SCREENSHOT_SYSTEM_IMAGE}"

if [[ "$DRY_RUN" == "1" ]]; then
  echo "Dry run complete. No build, install, or capture commands were executed."
  exit 0
fi

ADB_BIN="$(adb_bin)"
resolve_device "$ADB_BIN"
require_emulator_device "$ADB_BIN" "$ADB_SERIAL"
stabilize_device_for_screenshots "$ADB_BIN" "$ADB_SERIAL"
configure_screenshot_display "$ADB_BIN" "$ADB_SERIAL"
mkdir -p "$OUTPUT_DIR"
rm -f "$OUTPUT_DIR"/*.png "$OUTPUT_DIR"/*.jpg "$OUTPUT_DIR"/*.jpeg
rm -rf "$ARTIFACT_DIR"
mkdir -p "$ARTIFACT_DIR/screenshots" "$ARTIFACT_DIR/ui-dumps" "$ARTIFACT_DIR/activity-start"

if [[ "$SKIP_INSTALL" != "1" ]]; then
  if [[ "$SKIP_BUILD" != "1" ]]; then
    (
      cd "$ANDROID_DIR"
      ./gradlew "$GRADLE_ASSEMBLE_TASK"
    )
  fi
  APK_PATH="$(latest_debug_apk)"
  if [[ -z "$APK_PATH" ]]; then
    echo "No existing ${FORM_FACTOR} debug APK found. Run without --skip-build first." >&2
    exit 1
  fi
  "$ADB_BIN" -s "$ADB_SERIAL" install -r "$APK_PATH" >/dev/null
elif [[ "$SKIP_BUILD" != "1" ]]; then
  (
    cd "$ANDROID_DIR"
    ./gradlew "$GRADLE_ASSEMBLE_TASK"
  )
fi

"$ADB_BIN" -s "$ADB_SERIAL" shell pm clear ai.openclaw.app >/dev/null
"$ADB_BIN" -s "$ADB_SERIAL" shell pm grant ai.openclaw.app android.permission.RECORD_AUDIO >/dev/null
"$ADB_BIN" -s "$ADB_SERIAL" logcat -c >/dev/null 2>&1 || true

for scene in "${SCENES[@]}"; do
  output_path="${OUTPUT_DIR}/openclaw-${scene}.jpg"
  raw_path="${OUTPUT_DIR}/openclaw-${scene}.raw.png"
  artifact_path="${ARTIFACT_DIR}/screenshots/openclaw-${scene}.jpg"
  ui_dump_path="${ARTIFACT_DIR}/ui-dumps/openclaw-${scene}.xml"
  activity_start_path="${ARTIFACT_DIR}/activity-start/openclaw-${scene}.txt"
  "$ADB_BIN" -s "$ADB_SERIAL" shell am force-stop ai.openclaw.app >/dev/null
  "$ADB_BIN" -s "$ADB_SERIAL" shell input keyevent 224 >/dev/null 2>&1 || true
  "$ADB_BIN" -s "$ADB_SERIAL" shell wm dismiss-keyguard >/dev/null 2>&1 || true
  "$ADB_BIN" -s "$ADB_SERIAL" shell am start -W \
    -n "$ACTIVITY_COMPONENT" \
    --ez openclaw.screenshotMode true \
    --es openclaw.screenshotScene "$scene" >"$activity_start_path"
  wait_for_scene_ready "$ADB_BIN" "$ADB_SERIAL" "$scene" "$ui_dump_path"
  sleep "${ANDROID_SCREENSHOT_SETTLE_SECONDS:-0.5}"
  "$ADB_BIN" -s "$ADB_SERIAL" exec-out screencap -p >"$raw_path"
  normalize_capture_for_play "$raw_path" "$output_path"
  cp "$output_path" "$artifact_path"
  echo "Captured ${output_path}"
done

"$ADB_BIN" -s "$ADB_SERIAL" logcat -d >"$ARTIFACT_DIR/logcat.txt" 2>&1 || true
if [[ -n "$EMULATOR_LOG" && -f "$EMULATOR_LOG" ]]; then
  cp "$EMULATOR_LOG" "$ARTIFACT_DIR/emulator.log"
fi
write_artifact_manifest "$ADB_SERIAL"

echo "Android screenshots written to ${OUTPUT_DIR}"
echo "Android screenshot artifacts written to ${ARTIFACT_DIR}"
