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

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ANDROID_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
RESULTS_DIR="$ANDROID_DIR/benchmark/results"
CLASS_FILTER="ai.openclaw.android.benchmark.StartupMacrobenchmark#coldStartup"
BASELINE_JSON=""

usage() {
  cat <<'EOF'
Usage:
  ./scripts/perf-startup-benchmark.sh [--baseline <benchmarkData.json>]

Runs cold-start macrobenchmark only, then prints a compact summary.
Also saves a timestamped snapshot JSON under benchmark/results/.
If --baseline is omitted, compares against latest previous snapshot when available.
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --baseline)
      BASELINE_JSON="${2:-}"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown arg: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

if ! command -v jq >/dev/null 2>&1; then
  echo "jq required but missing." >&2
  exit 1
fi

if ! command -v adb >/dev/null 2>&1; then
  echo "adb required but missing." >&2
  exit 1
fi

device_count="$(adb devices | awk 'NR>1 && $2=="device" {c+=1} END {print c+0}')"
if [[ "$device_count" -lt 1 ]]; then
  echo "No connected Android device (adb state=device)." >&2
  exit 1
fi

mkdir -p "$RESULTS_DIR"

run_log="$(mktemp -t openclaw-android-bench.XXXXXX.log)"
trap 'rm -f "$run_log"' EXIT

cd "$ANDROID_DIR"

./gradlew :benchmark:connectedDebugAndroidTest \
  -Pandroid.testInstrumentationRunnerArguments.class="$CLASS_FILTER" \
  --console=plain \
  >"$run_log" 2>&1

latest_json="$(
  find "$ANDROID_DIR/benchmark/build/outputs/connected_android_test_additional_output/debug/connected" \
    -name '*benchmarkData.json' -type f \
    | while IFS= read -r file; do
        printf '%s\t%s\n' "$(stat -f '%m' "$file")" "$file"
      done \
    | sort -nr \
    | head -n1 \
    | cut -f2-
)"

if [[ -z "$latest_json" || ! -f "$latest_json" ]]; then
  echo "benchmarkData.json not found after run." >&2
  tail -n 120 "$run_log" >&2
  exit 1
fi

timestamp="$(date +%Y%m%d-%H%M%S)"
snapshot_json="$RESULTS_DIR/startup-$timestamp.json"
cp "$latest_json" "$snapshot_json"

median_ms="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.median' "$snapshot_json")"
min_ms="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.minimum' "$snapshot_json")"
max_ms="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.maximum' "$snapshot_json")"
cov="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.coefficientOfVariation' "$snapshot_json")"
device="$(jq -r '.context.build.model' "$snapshot_json")"
sdk="$(jq -r '.context.build.version.sdk' "$snapshot_json")"
runs_count="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.runs | length' "$snapshot_json")"

printf 'startup.cold.median_ms=%.3f min_ms=%.3f max_ms=%.3f cov=%.4f runs=%s device=%s sdk=%s\n' \
  "$median_ms" "$min_ms" "$max_ms" "$cov" "$runs_count" "$device" "$sdk"
echo "snapshot_json=$snapshot_json"

if [[ -z "$BASELINE_JSON" ]]; then
  BASELINE_JSON="$(
    find "$RESULTS_DIR" -name 'startup-*.json' -type f \
      | while IFS= read -r file; do
          if [[ "$file" == "$snapshot_json" ]]; then
            continue
          fi
          printf '%s\t%s\n' "$(stat -f '%m' "$file")" "$file"
        done \
      | sort -nr \
      | head -n1 \
      | cut -f2-
  )"
fi

if [[ -n "$BASELINE_JSON" ]]; then
  if [[ ! -f "$BASELINE_JSON" ]]; then
    echo "Baseline file missing: $BASELINE_JSON" >&2
    exit 1
  fi
  base_median="$(jq -r '.benchmarks[] | select(.name=="coldStartup") | .metrics.timeToInitialDisplayMs.median' "$BASELINE_JSON")"
  delta_ms="$(awk -v a="$median_ms" -v b="$base_median" 'BEGIN { printf "%.3f", (a-b) }')"
  delta_pct="$(awk -v a="$median_ms" -v b="$base_median" 'BEGIN { if (b==0) { print "nan" } else { printf "%.2f", ((a-b)/b)*100 } }')"
  echo "baseline_median_ms=$base_median delta_ms=$delta_ms delta_pct=$delta_pct%"
fi
