#!/bin/sh
set -eu
umask 077

ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
ENV_FILE="$ROOT/.env"
APK="$ROOT/android/dist-staging/who-need-help-staging.apk"
TEST_APK="$ROOT/android/dist-staging/who-need-help-staging-androidTest.apk"
run_id=$(date -u +%Y%m%d%H%M%S)-$$
image="who-need-help-android:staging-smoke-$run_id"
container="who-need-help-android-staging-smoke-$run_id"
avd_volume="who-need-help-android-avd-staging-smoke-$run_id"
output="$ROOT/output/android-staging-smoke/$run_id"
package=org.whoneedhelp.mobile.staging
activity=org.whoneedhelp.mobile.MainActivity

if [ ! -e /dev/kvm ]; then
  echo "/dev/kvm is required for the containerized Android emulator." >&2
  exit 1
fi

if [ ! -f "$ENV_FILE" ]; then
  echo "Missing $ENV_FILE." >&2
  exit 1
fi

if [ ! -s "$APK" ]; then
  echo "Missing staging APK: $APK. Run scripts/android-staging-build.sh first." >&2
  exit 1
fi

if [ ! -s "$TEST_APK" ]; then
  echo "Missing staging test APK: $TEST_APK. Run scripts/android-staging-build.sh first." >&2
  exit 1
fi

set -a
# shellcheck source=/dev/null
. "$ENV_FILE"
set +a

: "${WNH_BASE_URL:?Set WNH_BASE_URL in .env}"
: "${WNH_TRACKING_MIN_TIME_MS:?Set WNH_TRACKING_MIN_TIME_MS in .env}"
: "${WNH_TRACKING_HTTP_TIMEOUT_MS:?Set WNH_TRACKING_HTTP_TIMEOUT_MS in .env}"

case "$WNH_BASE_URL" in
  https://*/* | https://*) ;;
  *)
    echo "WNH_BASE_URL must be an HTTPS origin." >&2
    exit 1
    ;;
esac

origin_without_scheme=${WNH_BASE_URL#https://}

case "$origin_without_scheme" in
  "" | */* | *\?* | *\#* | *@*)
    echo "WNH_BASE_URL must be a credential-free HTTPS origin without a path." >&2
    exit 1
    ;;
esac

expected_host=${origin_without_scheme%%:*}

mkdir -p "$output"
chmod 700 "$ROOT/output" "$ROOT/output/android-staging-smoke" "$output"

cleanup() {
  status=$?
  trap - EXIT HUP INT TERM

  if docker inspect "$container" >/dev/null 2>&1; then
    docker exec "$container" adb logcat -d \
      >"$output/logcat.txt" 2>&1 || true
    docker exec "$container" adb shell dumpsys activity activities \
      >"$output/activities.txt" 2>&1 || true
    docker logs "$container" >"$output/emulator.log" 2>&1 || true
  fi

  docker rm -f "$container" >/dev/null 2>&1 || true
  docker volume rm -f "$avd_volume" >/dev/null 2>&1 || true
  docker image rm "$image" >/dev/null 2>&1 || true

  {
    printf 'container_absent='
    if docker inspect "$container" >/dev/null 2>&1; then
      printf 'false\n'
    else
      printf 'true\n'
    fi

    printf 'volume_absent='
    if docker volume inspect "$avd_volume" >/dev/null 2>&1; then
      printf 'false\n'
    else
      printf 'true\n'
    fi

    printf 'image_absent='
    if docker image inspect "$image" >/dev/null 2>&1; then
      printf 'false\n'
    else
      printf 'true\n'
    fi
  } >"$output/cleanup.txt"

  exit "$status"
}

trap cleanup EXIT HUP INT TERM

sha256sum "$APK" >"$output/apk.sha256"
sha256sum "$TEST_APK" >"$output/test-apk.sha256"

docker build \
  --build-arg "WNH_DEBUG_BASE_URL=$WNH_BASE_URL" \
  --build-arg "WNH_TRACKING_MIN_TIME_MS=$WNH_TRACKING_MIN_TIME_MS" \
  --build-arg "WNH_TRACKING_HTTP_TIMEOUT_MS=$WNH_TRACKING_HTTP_TIMEOUT_MS" \
  --build-arg \
    "ANDROID_EMULATOR_SYSTEM_IMAGE=system-images/android-37.0/google_apis_ps16k/x86_64" \
  --target emulator \
  --tag "$image" \
  "$ROOT/android" >"$output/image-build.txt"

docker volume create "$avd_volume" >"$output/avd-volume.txt"

docker run -d \
  --name "$container" \
  --device /dev/kvm \
  --mount \
    "type=volume,source=$avd_volume,target=/home/gradle/.android/avd/who_need_help_test.avd" \
  "$image" >"$output/container-id.txt"

if [ "$(docker inspect --format '{{.State.Running}}' "$container")" != "true" ]; then
  docker logs "$container" >"$output/emulator.log" 2>&1 || true
  echo "Android staging emulator exited before ADB became available; inspect $output/emulator.log." >&2
  exit 1
fi

docker exec "$container" adb wait-for-device

booted=
attempt=0
while [ "$attempt" -lt 90 ]; do
  booted=$(
    docker exec "$container" adb shell getprop sys.boot_completed 2>/dev/null |
      tr -d '\r'
  )

  if [ "$booted" = "1" ]; then
    break
  fi

  attempt=$((attempt + 1))
  sleep 2
done

if [ "$booted" != "1" ]; then
  echo "Android staging emulator did not finish booting." >&2
  exit 1
fi

docker exec "$container" adb shell input keyevent 82
docker exec "$container" adb shell settings put global window_animation_scale 0
docker exec "$container" adb shell settings put global transition_animation_scale 0
docker exec "$container" adb shell settings put global animator_duration_scale 0
docker cp "$APK" "$container:/tmp/who-need-help-staging.apk"
docker cp "$TEST_APK" "$container:/tmp/who-need-help-staging-androidTest.apk"
docker exec "$container" adb install -r /tmp/who-need-help-staging.apk \
  >"$output/install.txt"
docker exec "$container" adb install -r /tmp/who-need-help-staging-androidTest.apk \
  >"$output/test-install.txt"
docker exec "$container" adb shell pm list instrumentation \
  >"$output/instrumentation.txt"
docker exec "$container" adb shell dumpsys package "$package" \
  >"$output/package.txt"

network_ready=false
attempt=0
while [ "$attempt" -lt 45 ]; do
  if docker exec "$container" adb shell ping -c 1 -W 1 "$expected_host" \
    >"$output/network-current.txt" 2>&1; then
    network_ready=true
    break
  fi

  attempt=$((attempt + 1))
  sleep 1
done

if [ "$network_ready" != true ]; then
  echo "The Android emulator could not resolve and reach the staging host." >&2
  exit 1
fi

if ! grep -Fq "versionName=0.1.0-staging" "$output/package.txt"; then
  echo "The installed package is not the expected staging variant." >&2
  exit 1
fi

same_origin="$WNH_BASE_URL/safety"
external_origin=https://example.com/

if ! grep -Fq "Authority: \"$expected_host\"" "$output/package.txt"; then
  echo "The staging APK does not declare its exact HTTPS host." >&2
  exit 1
fi

if grep -Fq 'Authority: "example.com"' "$output/package.txt"; then
  echo "The staging APK incorrectly declares an external HTTPS host." >&2
  exit 1
fi

docker exec "$container" adb shell cmd package resolve-activity --brief \
  -a android.intent.action.VIEW \
  -c android.intent.category.BROWSABLE \
  -d "$same_origin" >"$output/same-origin-resolver.txt"

docker exec "$container" adb shell cmd package resolve-activity --brief \
  -a android.intent.action.VIEW \
  -c android.intent.category.BROWSABLE \
  -d "$external_origin" >"$output/external-origin-resolver.txt"

if grep -Fq "$package/" "$output/external-origin-resolver.txt"; then
  echo "The staging APK incorrectly claimed an external HTTPS origin." >&2
  exit 1
fi

docker exec "$container" adb shell pm get-app-links "$package" \
  >"$output/app-links.txt"

docker exec "$container" adb logcat -c
docker exec "$container" adb shell am start -W \
  -n "$package/$activity" >"$output/home-start.txt"

home_loaded=false
attempt=0
while [ "$attempt" -lt 45 ]; do
  docker exec "$container" adb logcat -d -s WhoNeedHelpWebView:D '*:S' \
    >"$output/webview-current.txt" 2>&1 || true

  if grep -Fq "Main-frame load finished: path=/" "$output/webview-current.txt"; then
    home_loaded=true
    break
  fi

  attempt=$((attempt + 1))
  sleep 2
done

if [ "$home_loaded" != true ]; then
  echo "The staging WebView did not finish loading the public home page." >&2
  exit 1
fi

docker exec "$container" adb shell uiautomator dump /sdcard/home-window.xml \
  >"$output/home-ui-dump-command.txt" 2>&1
docker exec "$container" adb exec-out cat /sdcard/home-window.xml \
  >"$output/home-window.xml"
docker exec "$container" adb exec-out screencap -p >"$output/home.png"

docker exec "$container" adb shell am start -W \
  -a android.intent.action.VIEW \
  -c android.intent.category.BROWSABLE \
  -d "$same_origin" \
  -n "$package/$activity" >"$output/safety-start.txt"

safety_loaded=false
attempt=0
while [ "$attempt" -lt 45 ]; do
  docker exec "$container" adb logcat -d -s WhoNeedHelpWebView:D '*:S' \
    >"$output/webview-current.txt" 2>&1 || true

  if grep -Fq "Main-frame load finished: path=/safety" "$output/webview-current.txt"; then
    safety_loaded=true
    break
  fi

  attempt=$((attempt + 1))
  sleep 2
done

if [ "$safety_loaded" != true ]; then
  echo "The same-origin Android deep link did not finish loading /safety." >&2
  exit 1
fi

docker exec "$container" adb shell uiautomator dump /sdcard/safety-window.xml \
  >"$output/safety-ui-dump-command.txt" 2>&1
docker exec "$container" adb exec-out cat /sdcard/safety-window.xml \
  >"$output/safety-window.xml"
docker exec "$container" adb exec-out screencap -p >"$output/safety.png"

set +e
docker exec "$container" adb shell am instrument -w -r \
  -e class org.whoneedhelp.mobile.PublicStagingInstrumentedTest \
  org.whoneedhelp.mobile.staging.test/androidx.test.runner.AndroidJUnitRunner \
  >"$output/dom-results.txt" 2>&1
dom_status=$?
set -e

if [ "$dom_status" -ne 0 ] \
  || ! grep -Eq '^OK \(1 test\)$' "$output/dom-results.txt" \
  || grep -Eq 'FAILURES!!!|INSTRUMENTATION_FAILED|Process crashed' \
    "$output/dom-results.txt"; then
  cat "$output/dom-results.txt" >&2
  echo "The staging WebView DOM assertions failed." >&2
  exit 1
fi

docker exec "$container" adb logcat -d -s WhoNeedHelpWebView:D '*:S' \
  >"$output/webview-after-dom.txt"
docker exec "$container" adb shell dumpsys activity activities \
  >"$output/activities-before-cleanup.txt"

if grep -Eqi \
  'Main-frame load failed|net::ERR_|ERR_CERT|SSL handshake failed|chromium.*crash' \
  "$output/webview-after-dom.txt"; then
  echo "Android staging logcat contains a public-page load or TLS failure." >&2
  exit 1
fi

if ! grep -Fq 'INSTRUMENTATION_CODE: -1' "$output/dom-results.txt"; then
  echo "The staging DOM runner did not finish normally." >&2
  exit 1
fi

{
  printf 'run_id=%s\n' "$run_id"
  printf 'android_api=37.0\n'
  printf 'package=%s\n' "$package"
  printf 'public_origin=%s\n' "$WNH_BASE_URL"
  printf 'home_loaded=true\n'
  printf 'home_dom_assertion=true\n'
  printf 'same_origin_manifest_filter=true\n'
  printf 'same_origin_deep_link_loaded=true\n'
  printf 'safety_dom_assertion=true\n'
  printf 'external_origin_manifest_filter=false\n'
  printf 'load_or_tls_errors=0\n'
} >"$output/summary.txt"

echo "Android public staging smoke passed."
echo "Evidence: $output"
