#!/usr/bin/env bash
#
# Check an AAB before uploading it to Play.
#
#   bash apps/mobile/scripts/verify-aab.sh [path-to.aab]
#
# Exists because "BUILD SUCCESSFUL" proves nothing about what is inside
# the artifact. A release build signed with the debug key builds cleanly,
# reports success, and is rejected by Play only after upload — that
# happened here once, and this is what caught it.
#
# Checks, in the order they would waste your time:
#   1. the archive is intact
#   2. it is signed with the release key, not the debug key
#   3. the permissions that were deliberately removed are actually gone
#   4. AD_ID is absent, matching the "no advertising ID" declaration
#   5. it is not debuggable
#   6. the JS bundle is present, so it is not a debug variant

set -euo pipefail

AAB="${1:-apps/mobile/android/app/build/outputs/bundle/release/app-release.aab}"

# The expected release certificate. If this ever changes, the app can no
# longer be updated on Play — so a mismatch is a hard failure, not a
# warning.
EXPECTED_CN="On AI Radar"

fails=0
ok()   { printf '  \033[32mok\033[0m    %s\n' "$1"; }
bad()  { printf '  \033[31mFAIL\033[0m  %s\n' "$1"; fails=$((fails+1)); }

[ -f "$AAB" ] || { echo "No AAB at $AAB"; exit 1; }

echo
echo "Verifying $AAB"
printf '  %s bytes\n\n' "$(stat -c%s "$AAB" 2>/dev/null || wc -c < "$AAB")"

# 1. intact ------------------------------------------------------------
if unzip -t "$AAB" >/dev/null 2>&1; then
  ok "valid archive"
else
  bad "archive is corrupt"
fi

# 2. signing -----------------------------------------------------------
SIG=$(unzip -l "$AAB" 2>/dev/null | awk '{print $4}' \
      | grep -E '^META-INF/.*\.(RSA|DSA|EC)$' | head -1 || true)

if [ -z "$SIG" ]; then
  bad "not signed at all"
else
  TMP=$(mktemp)
  unzip -p "$AAB" "$SIG" > "$TMP" 2>/dev/null
  OWNER=$(keytool -printcert -file "$TMP" 2>/dev/null | grep -m1 '^Owner:' || true)
  rm -f "$TMP"

  if printf '%s' "$OWNER" | grep -q "CN=$EXPECTED_CN"; then
    ok "signed with the release key ($EXPECTED_CN)"
  elif printf '%s' "$OWNER" | grep -qi 'Android Debug'; then
    bad "SIGNED WITH THE DEBUG KEY — Play will reject this"
    printf '        %s\n' "$OWNER"
  else
    bad "signed by an unexpected key"
    printf '        %s\n' "$OWNER"
  fi
fi

# 3-5. manifest --------------------------------------------------------
DIR=$(mktemp -d)
unzip -o -q "$AAB" "base/manifest/AndroidManifest.xml" -d "$DIR" 2>/dev/null
M="$DIR/base/manifest/AndroidManifest.xml"

if [ -f "$M" ]; then
  # The manifest is protobuf, so read printable strings out of it rather
  # than parsing it properly. Enough to answer yes/no questions.
  TEXT=$(tr -c '[:print:]\n' ' ' < "$M")

  for perm in SYSTEM_ALERT_WINDOW READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE; do
    if printf '%s' "$TEXT" | grep -q "$perm"; then
      bad "$perm is still declared"
    else
      ok "$perm removed"
    fi
  done

  if printf '%s' "$TEXT" | grep -q 'AD_ID'; then
    bad "AD_ID is declared — contradicts the advertising ID declaration"
  else
    ok "no AD_ID permission"
  fi

  if printf '%s' "$TEXT" | grep -qi 'debuggable'; then
    bad "android:debuggable is set"
  else
    ok "not debuggable"
  fi
else
  bad "could not read the manifest"
fi
rm -rf "$DIR"

# 6. release variant ---------------------------------------------------
# In an AAB the bundle is at base/assets/, not assets/ as in an APK.
#
# `grep -c` rather than `grep -q`: under `set -o pipefail`, grep -q exits
# as soon as it matches, unzip gets SIGPIPE, and the pipeline reports
# failure even though the match succeeded. That produced a false "no JS
# bundle" on a bundle that was plainly there.
# LC_ALL=C so grep matches bytes rather than interpreting the listing as
# text in the ambient locale — the file paths are ASCII, and a UTF-8
# locale on a listing containing other bytes can make a plain match fail.
BUNDLES=$(unzip -l "$AAB" 2>/dev/null | LC_ALL=C grep -c 'index\.android\.bundle' || true)
if [ "${BUNDLES:-0}" -gt 0 ]; then
  ok "JS bundle present (release variant)"
else
  bad "no JS bundle — this looks like a debug build"
fi

echo
if [ "$fails" -eq 0 ]; then
  printf '\033[32mReady to upload.\033[0m\n\n'
else
  printf '\033[31m%s check(s) failed — do not upload.\033[0m\n\n' "$fails"
  exit 1
fi
