#!/usr/bin/env bash
# Build a signed TWA APK for the MegaTrust Support PWA, non-interactively, using
# `expect` to answer bubblewrap/keytool prompts. Runs in a throwaway container.
set -e

PKG="com.megatrust.support"
HOST="system.appsanad.com"
MANIFEST="https://system.appsanad.com/manifest.webmanifest"
KS_PASS="MegaTrust2026Apk"
OUT=/build/out
SDK=/build/android-sdk        # persisted in the volume so re-runs skip the download

mkdir -p /build/app "$OUT"

echo "### 1. base tools"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq openjdk-17-jdk-headless unzip curl expect >/dev/null
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))

echo "### 2. android sdk (cached in volume if already present)"
export ANDROID_HOME="$SDK"
export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH"
if [ ! -d "$SDK/platforms/android-34" ]; then
  mkdir -p "$SDK/cmdline-tools"
  cd /tmp
  curl -sSL -o cmdtools.zip https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
  rm -rf "$SDK/cmdline-tools/latest"
  unzip -q cmdtools.zip -d "$SDK/cmdline-tools"
  mv "$SDK/cmdline-tools/cmdline-tools" "$SDK/cmdline-tools/latest"
  yes | sdkmanager --licenses >/dev/null 2>&1 || true
  sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0" >/dev/null
else
  echo "sdk already present — skipping download"
fi
# Bubblewrap's validatePath() insists the SDK root contains a `tools` (or `bin`)
# folder — the legacy layout. Modern SDKs put it under cmdline-tools/latest, so
# expose it where bubblewrap looks.
ln -sfn "$ANDROID_HOME/cmdline-tools/latest" "$ANDROID_HOME/tools"

echo "### 3. bubblewrap + config"
npm i -g @bubblewrap/cli >/tmp/npm.log 2>&1 || { echo "npm install failed"; tail -20 /tmp/npm.log; exit 1; }
mkdir -p /root/.bubblewrap
printf '{ "jdkPath": "%s", "androidSdkPath": "%s" }\n' "$JAVA_HOME" "$ANDROID_HOME" > /root/.bubblewrap/config.json

echo "### 4a. pre-create the signing keystore at bubblewrap's default path"
cd /build/app
rm -f twa-manifest.json android.keystore
keytool -genkeypair -v \
  -keystore /build/app/android.keystore \
  -alias android -keyalg RSA -keysize 2048 -validity 10000 \
  -storepass "$KS_PASS" -keypass "$KS_PASS" \
  -dname "CN=MegaTrust Support, OU=Support, O=MegaTrust, L=Riyadh, ST=Riyadh, C=SA" >/dev/null 2>&1
echo "keystore ready at /build/app/android.keystore"

echo "### 4b. init via expect (keystore already exists, so no identity prompts)"
cat > /tmp/init.exp <<EXPECT
# (?i) is NOT honoured by this expect build, so patterns match the ACTUAL casing
# of each prompt. No greedy "?" catch-all — it would match the "?" at the start
# of a prompt and beat the specific text. Unrecognised prompts fall to timeout,
# which accepts the default.
set timeout 5
spawn bubblewrap init --manifest $MANIFEST --directory /build/app
# Patterns are braced {} so Tcl does not treat [..] as command substitution.
# The password pattern uses a negative lookahead (?!\*) so it matches only the
# FRESH prompt, not the masked-asterisk redraw it echoes back — otherwise expect
# re-sends the password on every asterisk and loops forever.
expect {
  -re {Organizational Unit}     { send "Support\r"; exp_continue }
  -re {and Last names}          { send "MegaTrust Support\r"; exp_continue }
  -re {your Organization}       { send "MegaTrust\r"; exp_continue }
  -re {Organization}            { send "MegaTrust\r"; exp_continue }
  -re {City or Locality}        { send "Riyadh\r"; exp_continue }
  -re {State or Province}       { send "Riyadh\r"; exp_continue }
  -re {[Cc]ountry}              { send "SA\r"; exp_continue }
  -re {correct}                 { send "yes\r"; exp_continue }
  -re {[Pp]assword[^:]*: (?!\*)} { send "$KS_PASS\r"; exp_continue }
  timeout                       { send "\r"; exp_continue }
  eof
}
EXPECT
expect -f /tmp/init.exp > /tmp/init.log 2>&1 || true
echo "--- init tail ---"; tail -8 /tmp/init.log
if [ ! -f twa-manifest.json ]; then echo "INIT FAILED — no twa-manifest.json"; tail -40 /tmp/init.log; exit 1; fi

echo "### 5. force our identity + point at the generated key"
node - <<NODE
const fs=require('fs'), p='/build/app/twa-manifest.json';
const m=JSON.parse(fs.readFileSync(p,'utf8'));
Object.assign(m,{
  packageId:"$PKG", host:"$HOST", name:"MegaTrust Support", launcherName:"MT Support",
  display:"standalone", themeColor:"#0b3d2e", navigationColor:"#0b3d2e",
  navigationColorDark:"#0b3d2e", backgroundColor:"#0b3d2e", startUrl:"/m",
  webManifestUrl:"$MANIFEST", iconUrl:"https://$HOST/app-icons/icon-512-any.png",
  maskableIconUrl:"https://$HOST/app-icons/icon-512.png",
  orientation:"portrait", fallbackType:"customtabs", enableNotifications:false,
  appVersionName:"1.0.0", appVersionCode:1, shortcuts:[]
});
fs.writeFileSync(p, JSON.stringify(m,null,2));
console.log("packageId="+m.packageId, "signingKey="+JSON.stringify(m.signingKey));
NODE

echo "### 6. regenerate project from the edited manifest, then build"
export BUBBLEWRAP_KEYSTORE_PASSWORD="$KS_PASS"
export BUBBLEWRAP_KEY_PASSWORD="$KS_PASS"
printf 'y\ny\n' | bubblewrap update >/tmp/update.log 2>&1 || true
cat > /tmp/build.exp <<EXPECT
set timeout 30
spawn bubblewrap build --skipPwaValidation
expect {
  -re {[Pp]assword}          { send "$KS_PASS\r"; exp_continue }
  -re {[Gg]enerate}          { send "\r"; exp_continue }
  timeout                    { send "\r"; exp_continue }
  eof
}
EXPECT
expect -f /tmp/build.exp > /tmp/build.log 2>&1 || true
echo "--- update.log tail ---"; sed -E 's/\x1b\[[0-9;?]*[a-zA-Z]//g' /tmp/update.log | tail -8
echo "--- build.log tail ---"; sed -E 's/\x1b\[[0-9;?]*[a-zA-Z]//g' /tmp/build.log | tail -25

echo "### 7. collect outputs"
cp -v /build/app/*.apk "$OUT/" 2>/dev/null || true
# find the keystore bubblewrap created and copy it + fingerprint
KS=$(node -e "console.log((JSON.parse(require('fs').readFileSync('/build/app/twa-manifest.json')).signingKey||{}).path||'')")
[ -f "$KS" ] && cp -v "$KS" "$OUT/megatrust-support.keystore"
ALIAS=$(node -e "console.log((JSON.parse(require('fs').readFileSync('/build/app/twa-manifest.json')).signingKey||{}).alias||'android')")
if [ -f "$OUT/megatrust-support.keystore" ]; then
  keytool -list -v -keystore "$OUT/megatrust-support.keystore" -alias "$ALIAS" -storepass "$KS_PASS" \
    | grep -i "SHA256:" | head -1 | sed 's/.*SHA256: *//' > "$OUT/fingerprint.txt"
fi
echo "=== OUTPUTS ==="; ls -la "$OUT"
echo "=== FINGERPRINT ==="; cat "$OUT/fingerprint.txt" 2>/dev/null || echo "(none)"
echo "### DONE"
