#!/usr/bin/env bash
#
# publish-mobile-update.sh
# ------------------------
# Publishes the LogShip Mobile Android build into the ERP's server-side release channel
# (data/mobile-releases/ on the app host, served via app.logship.de — see
# server/utils/mobileReleases.ts) WITHOUT an ERP deployment:
#
#     android/update-files/logship-mobile.apk + version.json
#         --POST multipart-->  <ERP_BASE>/api/settings/mobile-app/publish
#
# The server archives the replaced APK into history/, merges history.json, prunes old builds
# and writes version.json last. Auth = the non-expiring service token (IDEMPIERETOKEN) read
# from .env-prod (never printed). The same endpoint backs the upload form at
# Settings → Mobile App in the ERP UI.
#
# Usage:
#     scripts/publish-mobile-update.sh            # publish to https://app.logship.de
#     scripts/publish-mobile-update.sh --force    # allow same/lower versionCode (re-publish)
#     ERP_BASE=http://localhost:3010 scripts/publish-mobile-update.sh   # local dev server
#     ERP_ENV_FILE=.env scripts/publish-mobile-update.sh                # token from another env file
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
UPDATE_DIR="$REPO_ROOT/android/update-files"
APK_LOCAL="$UPDATE_DIR/logship-mobile.apk"
VERSION_LOCAL="$UPDATE_DIR/version.json"
ERP_BASE="${ERP_BASE:-https://app.logship.de}"
ERP_ENV_FILE="${ERP_ENV_FILE:-$REPO_ROOT/.env-prod}"

bold() { printf '\033[1m%s\033[0m\n' "$*"; }
err()  { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; }
ok()   { printf '\033[32m✔\033[0m %s\n' "$*"; }

FORCE=0
for a in "$@"; do
  case "$a" in
    --force) FORCE=1 ;;
    -h|--help) sed -n '3,22p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
    *) err "unknown option: $a"; exit 1 ;;
  esac
done

for f in "$APK_LOCAL" "$VERSION_LOCAL"; do
  [ -f "$f" ] || { err "Missing $f — run scripts/release-app.sh (or stage the APK) first"; exit 1; }
done
[ -f "$ERP_ENV_FILE" ] || { err "Env file $ERP_ENV_FILE not found (set ERP_ENV_FILE)"; exit 1; }

# Service token, read without echoing it anywhere.
TOKEN="$(grep '^IDEMPIERETOKEN=' "$ERP_ENV_FILE" | head -1 | sed "s/^IDEMPIERETOKEN=//; s/^'//; s/'\$//; s/^\"//; s/\"\$//")"
[ -n "$TOKEN" ] || { err "IDEMPIERETOKEN not found in $ERP_ENV_FILE"; exit 1; }

json_field() { node -e 'const j=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8"));process.stdout.write(String(j[process.argv[2]]??""))' "$1" "$2"; }
new_vn="$(json_field "$VERSION_LOCAL" versionName)"
new_vc="$(json_field "$VERSION_LOCAL" versionCode)"

# APK ↔ version.json sanity check (the updater keys off version.json)
find_aapt() {
  local base cand
  for base in "${ANDROID_HOME:-}" "${ANDROID_SDK_ROOT:-}" "$HOME/Library/Android/sdk" "$HOME/Android/Sdk"; do
    [ -n "$base" ] || continue
    cand="$(ls -1 "$base"/build-tools/*/aapt 2>/dev/null | sort -V | tail -1 || true)"
    [ -n "$cand" ] && { printf '%s' "$cand"; return 0; }
  done
  command -v aapt >/dev/null 2>&1 && { command -v aapt; return 0; }
  return 1
}
AAPT="$(find_aapt || true)"
if [ -n "${AAPT:-}" ]; then
  badging="$("$AAPT" dump badging "$APK_LOCAL" 2>/dev/null | grep '^package:' || true)"
  apk_vn="$(printf '%s' "$badging" | sed -n "s/.*versionName='\([^']*\)'.*/\1/p")"
  apk_vc="$(printf '%s' "$badging" | sed -n "s/.*versionCode='\([^']*\)'.*/\1/p")"
  bold "Version check"
  printf '  APK         : versionName=%s versionCode=%s\n' "$apk_vn" "$apk_vc"
  printf '  version.json: versionName=%s versionCode=%s\n' "$new_vn" "$new_vc"
  if [ "$apk_vn" != "$new_vn" ] || [ "$apk_vc" != "$new_vc" ]; then
    err "version.json does NOT match the APK — devices compare version.json, a mismatch breaks updates."
    read -rp "Publish anyway? [y/N] " ans
    case "$ans" in y|Y) ;; *) exit 1;; esac
  else
    ok "version.json matches the APK"
  fi
else
  printf 'aapt not found — skipping APK/version.json match check.\n'
fi

bold "Publishing $new_vn (code $new_vc) → $ERP_BASE/api/settings/mobile-app/publish"
RESP="$(curl -sS --fail-with-body --max-time 600 \
  -H "Authorization: Bearer $TOKEN" \
  -F "apk=@$APK_LOCAL;type=application/vnd.android.package-archive" \
  -F "version=@$VERSION_LOCAL;type=application/json" \
  $( [ "$FORCE" = "1" ] && printf -- '-F force=1' ) \
  "$ERP_BASE/api/settings/mobile-app/publish" 2>&1)" || { err "Publish request failed:"; printf '%s\n' "$RESP" >&2; exit 1; }

STATUS="$(printf '%s' "$RESP" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const j=JSON.parse(s);console.log(j.status??"")}catch{console.log("")}})')"
if [ "$STATUS" != "200" ]; then
  err "Server rejected the release:"; printf '%s\n' "$RESP" >&2; exit 1
fi
printf '%s\n' "$RESP" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const j=JSON.parse(s);const m=j.manifest||{};console.log("  "+j.message);if(j.archived)console.log("  archived: "+j.archived);console.log("  sha256  : "+(m.sha256||"?"));console.log("  size    : "+((m.size||0)/1048576).toFixed(1)+" MB");console.log("  apkUrl  : "+(m.apkUrl||"?").replace(/\/api\/public\/mobile\/[^/]+\//,"/api/public/mobile/<token>/"))})'
ok "published $new_vn (code $new_vc)"

# Verify what devices will see now.
LIVE="$(curl -sS -H "Authorization: Bearer $TOKEN" "$ERP_BASE/api/mobile/app-version" 2>/dev/null || true)"
live_vc="$(printf '%s' "$LIVE" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{console.log(JSON.parse(s).versionCode??"")}catch{console.log("")}})')"
if [ "$live_vc" = "$new_vc" ]; then ok "live manifest reports versionCode $live_vc"; else err "live manifest reports versionCode '$live_vc' (expected $new_vc)"; exit 1; fi
