#!/bin/sh
set -eu

package_name="co.childphone.agent.managed"
admin_component="$package_name/co.childphone.core.ui.ChildPhoneDeviceAdminReceiver"
expected_version_name="0.18.6"
expected_version_code="26"
expected_apk_sha256="c5a401262d2de5ca467e77f2c0b3e0e451d9bb13f1e8bbb9854aade97f215332"
expected_certificate_sha256="111129763a0d29cbc2e9110babe2ef231a0beba9293c5f002e3b626afa0f911a"
expected_home_state="${CHILDPHONE_EXPECT_HOME_STATE:-auto}"

adb_bin="${ADB_BIN:-adb}"
serial="${1:-}"
script_name="${0##*/}"
pass_count=0
fail_count=0

usage() {
  echo "Usage: sh $script_name ANDROID_SERIAL" >&2
  echo "Run this only against a factory-reset spare phone after ChildPhone QR enrollment." >&2
  exit 2
}

pass() {
  pass_count=$((pass_count + 1))
  printf '[PASS] %s\n' "$1"
}

fail() {
  fail_count=$((fail_count + 1))
  printf '[FAIL] %s\n' "$1"
}

info() {
  printf '[INFO] %s\n' "$1"
}

safe_label() {
  tr -d '\r\n\t' | cut -c1-80
}

case "$serial" in
  ""|-*) usage ;;
esac
case "$expected_home_state" in
  auto|android|childphone) ;;
  *)
    echo "CHILDPHONE_EXPECT_HOME_STATE must be auto, android, or childphone." >&2
    exit 2
    ;;
esac

if ! command -v "$adb_bin" >/dev/null 2>&1; then
  echo "adb was not found. Install Android Platform Tools and try again." >&2
  exit 2
fi

device_state="$($adb_bin devices | awk -v serial="$serial" '$1 == serial { print $2; exit }')"
if [ "$device_state" != "device" ]; then
  echo "The selected Android device is not connected and authorized (state: ${device_state:-missing})." >&2
  exit 2
fi

adb_device() {
  "$adb_bin" -s "$serial" "$@"
}

manufacturer="$(adb_device shell getprop ro.product.manufacturer | safe_label)"
model="$(adb_device shell getprop ro.product.model | safe_label)"
android_sdk="$(adb_device shell getprop ro.build.version.sdk | safe_label)"
qemu="$(adb_device shell getprop ro.kernel.qemu | safe_label)"

echo "ChildPhone Managed 0.18.6 physical-device preflight"
echo "Read-only scope: device model/SDK, ChildPhone package metadata, Device Owner, launcher,"
echo "permission booleans, and installed APK bytes. No app data, coordinates, notifications,"
echo "messages, phrases, pairing secrets, tokens, accounts, or personal files are read."
echo
printf 'Device: %s %s · Android SDK %s\n' "${manufacturer:-Unknown}" "${model:-Unknown}" "${android_sdk:-Unknown}"

is_emulator=0
case "$serial" in emulator-*) is_emulator=1 ;; esac
if [ "$qemu" = "1" ]; then is_emulator=1; fi
if [ "$is_emulator" -eq 1 ]; then
  if [ "${CHILDPHONE_ALLOW_EMULATOR:-0}" = "1" ]; then
    info "Emulator override is active for script testing; this does not satisfy physical acceptance."
  else
    fail "Physical hardware check (an emulator was detected)"
  fi
else
  pass "Physical Android hardware detected"
fi

package_dump="$(adb_device shell dumpsys package "$package_name" 2>/dev/null | tr -d '\r')"
if printf '%s\n' "$package_dump" | grep -F "Package [$package_name]" >/dev/null 2>&1; then
  pass "ChildPhone Managed package is installed"
else
  fail "ChildPhone Managed package is installed"
fi

version_name="$(printf '%s\n' "$package_dump" | sed -n 's/^[[:space:]]*versionName=\([^[:space:]]*\).*/\1/p' | head -n 1)"
version_code="$(printf '%s\n' "$package_dump" | sed -n 's/^[[:space:]]*versionCode=\([0-9][0-9]*\).*/\1/p' | head -n 1)"
if [ "$version_name" = "$expected_version_name" ] && [ "$version_code" = "$expected_version_code" ]; then
  pass "Installed version is $expected_version_name ($expected_version_code)"
else
  fail "Installed version is $expected_version_name ($expected_version_code); found ${version_name:-missing} (${version_code:-missing})"
fi

owners="$(adb_device shell dpm list-owners 2>/dev/null | tr -d '\r')"
if printf '%s\n' "$owners" | grep -F "$admin_component" >/dev/null 2>&1 &&
   printf '%s\n' "$owners" | grep -F "DeviceOwner" >/dev/null 2>&1; then
  pass "ChildPhone is Device Owner"
else
  fail "ChildPhone is Device Owner"
fi

launcher="$(adb_device shell cmd package resolve-activity --brief \
  -a android.intent.action.MAIN \
  -c android.intent.category.LAUNCHER \
  "$package_name" 2>/dev/null | tr -d '\r')"
if printf '%s\n' "$launcher" | grep -F "$package_name/" >/dev/null 2>&1; then
  pass "Child-visible launcher activity resolves"
else
  fail "Child-visible launcher activity resolves"
fi

home_component="$package_name/.ManagedHomeActivity"
home_candidates="$(adb_device shell cmd package query-activities --brief --user 0 \
  -a android.intent.action.MAIN \
  -c android.intent.category.HOME 2>/dev/null | tr -d '\r' || true)"
current_home="$(adb_device shell cmd package resolve-activity --brief --user 0 \
  -a android.intent.action.MAIN \
  -c android.intent.category.HOME 2>/dev/null | tr -d '\r' || true)"
home_component_visible=0
home_is_default=0
if printf '%s\n' "$home_candidates" | grep -F "$home_component" >/dev/null 2>&1; then
  home_component_visible=1
fi
if printf '%s\n' "$current_home" | grep -F "$home_component" >/dev/null 2>&1; then
  home_is_default=1
fi

if [ -z "$home_candidates" ] ||
   printf '%s\n%s\n' "$home_candidates" "$current_home" | grep -Ei 'unknown command|not found|error:' >/dev/null 2>&1; then
  info "Android Home resolver check is unavailable on this manufacturer build"
elif [ "$home_component_visible" -eq "$home_is_default" ]; then
  pass "ChildPhone Home component exposure matches Android's current default Home"
else
  fail "ChildPhone Home component exposure matches Android's current default Home"
fi

case "$expected_home_state" in
  android)
    if [ "$home_component_visible" -eq 0 ] && [ "$home_is_default" -eq 0 ]; then
      pass "Android Home is restored and inactive ChildPhone Home is not exposed"
    else
      fail "Android Home is restored and inactive ChildPhone Home is not exposed"
    fi
    ;;
  childphone)
    if [ "$home_component_visible" -eq 1 ] && [ "$home_is_default" -eq 1 ]; then
      pass "ChildPhone Home is enabled and selected as Android's default Home"
    else
      fail "ChildPhone Home is enabled and selected as Android's default Home"
    fi
    ;;
  auto)
    if [ "$home_is_default" -eq 1 ]; then
      info "Current Home: ChildPhone Home"
    else
      info "Current Home: Android or manufacturer launcher"
    fi
    ;;
esac

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT INT TERM
installed_apk="$tmp_dir/installed.apk"
package_paths="$(adb_device shell pm path "$package_name" 2>/dev/null | tr -d '\r')"
apk_path="$(printf '%s\n' "$package_paths" | sed -n 's/^package:\(.*\/base\.apk\)$/\1/p' | head -n 1)"
if [ -z "$apk_path" ]; then
  apk_path="$(printf '%s\n' "$package_paths" | sed -n 's/^package://p' | head -n 1)"
fi

if [ -n "$apk_path" ] && adb_device exec-out cat "$apk_path" > "$installed_apk" 2>/dev/null; then
  if command -v shasum >/dev/null 2>&1; then
    installed_sha256="$(shasum -a 256 "$installed_apk" | awk '{ print $1 }')"
  elif command -v sha256sum >/dev/null 2>&1; then
    installed_sha256="$(sha256sum "$installed_apk" | awk '{ print $1 }')"
  else
    installed_sha256=""
  fi
  if [ "$installed_sha256" = "$expected_apk_sha256" ]; then
    pass "Installed APK matches the checksum-pinned 0.18.6 signed release"
  else
    fail "Installed APK matches the checksum-pinned 0.18.6 signed release"
  fi
else
  fail "Installed APK can be read for release verification"
fi

apksigner_bin="${APKSIGNER_BIN:-}"
if [ -z "$apksigner_bin" ]; then
  sdk_root="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-$HOME/Library/Android/sdk}}"
  for candidate in "$sdk_root"/build-tools/*/apksigner; do
    if [ -x "$candidate" ]; then apksigner_bin="$candidate"; fi
  done
fi

if [ -s "$installed_apk" ] && [ -n "$apksigner_bin" ] && [ -x "$apksigner_bin" ]; then
  certificate_sha256="$($apksigner_bin verify --print-certs "$installed_apk" 2>/dev/null \
    | sed -n 's/^Signer #1 certificate SHA-256 digest: //p' \
    | head -n 1 \
    | tr 'A-F' 'a-f')"
  if [ "$certificate_sha256" = "$expected_certificate_sha256" ]; then
    pass "Installed APK uses the published 0.18.6 release certificate"
  else
    fail "Installed APK uses the published 0.18.6 release certificate"
  fi
else
  fail "Android apksigner is available for certificate verification"
fi

if printf '%s\n' "$package_dump" | grep -F 'android.permission.ACCESS_FINE_LOCATION: granted=true' >/dev/null 2>&1; then
  info "Optional GPS permission: granted"
else
  info "Optional GPS permission: off"
fi

if printf '%s\n' "$package_dump" | grep -F 'android.permission.POST_NOTIFICATIONS: granted=true' >/dev/null 2>&1; then
  info "Optional ongoing-notification permission: granted"
else
  info "Optional ongoing-notification permission: off"
fi

notification_listeners="$(adb_device shell settings get secure enabled_notification_listeners 2>/dev/null | tr -d '\r')"
if printf '%s\n' "$notification_listeners" | grep -F "$package_name/" >/dev/null 2>&1; then
  info "Optional communication Notification Access: granted"
else
  info "Optional communication Notification Access: off"
fi

echo
if [ "$fail_count" -eq 0 ]; then
  printf 'Core preflight: PASS (%s checks)\n' "$pass_count"
else
  printf 'Core preflight: FAIL (%s passed, %s failed)\n' "$pass_count" "$fail_count"
fi
echo "Manual checks still required:"
echo "1. Open ChildPhone and require Setup readiness > Enrollment core: PASS."
echo "2. Run each chosen feature with harmless test data and confirm its ongoing notice."
echo "3. Restore the disposable blocked app, stop optional monitoring, and delete local histories."
echo "4. Disconnect and delete the disposable family link, then factory reset the spare phone."

if [ "$fail_count" -ne 0 ]; then exit 1; fi
