#!/usr/bin/env bash
# Generate v0 OTA artifacts for one APK (stdout = channel stable.json).
#
# Usage:
#   ./scripts/generate-ota-v0.sh path/to/app-release.apk https://host[:port] [out-dir] [channel]
#
#   channel — JSON file under v0/ota/channel/ (default: stable). Use staging for QA.
#   RELEASE_NOTES — optional env, embedded in manifest.
#
#   channel — JSON under v0/ota/channel/ (stable, staging, dev, nightly, or custom)
# Writes under out-dir (default: ./ota-publish):
#   v0/ota/channel/<channel>.json
#   v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_manifest.json
#   v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_sign.json
#   v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otapkg
#   v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otabundle.zip  (STORE zip)
set -euo pipefail

apk="${1:?APK path required}"
host_base="${2:?Base URL required, e.g. https://192.168.1.1:8080}"
out_dir="${3:-ota-publish}"
channel="${4:-stable}"
release_notes="${RELEASE_NOTES:-}"
json_notes() {
  if command -v jq >/dev/null 2>&1; then
    jq -n --arg n "$release_notes" '$n'
  else
    local esc="${release_notes//\\/\\\\}"
    esc="${esc//\"/\\\"}"
    esc="${esc//$'\n'/\\n}"
    esc="${esc//$'\r'/}"
    printf '"%s"' "$esc"
  fi
}
NOTES_JSON="$(json_notes)"

if [[ ! -f "$apk" ]]; then
  echo "APK not found: $apk" >&2
  exit 1
fi

pad2() { printf '%02d' "$1"; }

major="" minor="" build=""
if command -v aapt >/dev/null 2>&1; then
  badging="$(aapt dump badging "$apk" 2>/dev/null || true)"
  version_code="$(echo "$badging" | sed -n "s/.*versionCode='\([^']*\)'.*/\1/p" | head -1)"
  version_name="$(echo "$badging" | sed -n "s/.*versionName='\([^']*\)'.*/\1/p" | head -1)"
  if [[ -n "${version_code:-}" ]]; then
    major=$((version_code / 10000))
    minor=$(((version_code / 100) % 100))
    build=$((version_code % 100))
  fi
fi

if [[ -z "${major:-}" ]]; then
  echo "Could not read versionCode from APK (install build-tools / aapt)." >&2
  exit 1
fi

maj_p="$(pad2 "$major")"
min_p="$(pad2 "$minor")"
bld_p="$(pad2 "$build")"
ver_p="${maj_p}.${min_p}.${bld_p}"
base="${host_base%/}/v0/ota/00/${maj_p}/${ver_p}"
artifact_base="${base}/android_cast_${ver_p}.${bld_p}"
apk_url="${artifact_base}.otapkg"
sign_url="${artifact_base}_sign.json"
manifest_url="${artifact_base}_manifest.json"
bundle_url="${artifact_base}.otabundle.zip"
sha256="$(sha256sum "$apk" | awk '{print $1}')"
apk_size="$(stat -c%s "$apk" 2>/dev/null || wc -c <"$apk" | tr -d ' ')"

rel_root="${out_dir}/v0/ota"
rel_dir="${rel_root}/00/${maj_p}/${ver_p}"
mkdir -p "${rel_dir}" "${rel_root}/channel"

pkg_name="android_cast_${ver_p}.${bld_p}.otapkg"
cp -f "$apk" "${rel_dir}/${pkg_name}"

sign_name="android_cast_${ver_p}.${bld_p}_sign.json"
manifest_name="android_cast_${ver_p}.${bld_p}_manifest.json"
bundle_name="android_cast_${ver_p}.${bld_p}.otabundle.zip"

cat >"${rel_dir}/${sign_name}" <<EOF
{
  "schema": "v0",
  "sha256": "${sha256}"
}
EOF

cat >"${rel_dir}/${manifest_name}" <<EOF
{
  "schema": "v0",
  "major": ${major},
  "minor": ${minor},
  "build": ${build},
  "versionName": "${version_name:-${major}.${minor}.${build}}",
  "apkUrl": "${apk_url}",
  "signUrl": "${sign_url}",
  "sizeBytes": ${apk_size},
  "mandatory": false,
  "releaseNotes": ${NOTES_JSON}
}
EOF

bundle_stage="$(mktemp -d)"
trap 'rm -rf "${bundle_stage}"' EXIT
cp -f "${rel_dir}/${manifest_name}" "${bundle_stage}/manifest.json"
cp -f "${rel_dir}/${sign_name}" "${bundle_stage}/sign.json"
cp -f "$apk" "${bundle_stage}/package.apk"
# -0 = STORED (no re-compression of the APK)
( cd "${bundle_stage}" && zip -0 -q -X "${rel_dir}/${bundle_name}" manifest.json sign.json package.apk )
bundle_sha256="$(sha256sum "${rel_dir}/${bundle_name}" | awk '{print $1}')"
bundle_size="$(stat -c%s "${rel_dir}/${bundle_name}" 2>/dev/null || wc -c <"${rel_dir}/${bundle_name}" | tr -d ' ')"

# Patch manifest with bundle fields (jq optional; use temp file + heredoc rewrite)
cat >"${rel_dir}/${manifest_name}" <<EOF
{
  "schema": "v0",
  "major": ${major},
  "minor": ${minor},
  "build": ${build},
  "versionName": "${version_name:-${major}.${minor}.${build}}",
  "apkUrl": "${apk_url}",
  "signUrl": "${sign_url}",
  "sizeBytes": ${apk_size},
  "bundleUrl": "${bundle_url}",
  "bundleSha256": "${bundle_sha256}",
  "bundleSizeBytes": ${bundle_size},
  "mandatory": false,
  "releaseNotes": ${NOTES_JSON}
}
EOF

channel_file="${rel_root}/channel/${channel}.json"
cat >"${channel_file}" <<EOF
{
  "schema": "v0",
  "manifestUrl": "${manifest_url}"
}
EOF

echo "Published v0 OTA under ${out_dir}/v0/ota" >&2
echo "Channel: ${host_base%/}/v0/ota/channel/${channel}.json" >&2
echo "Bundle: ${bundle_url} (${bundle_size} bytes)" >&2
cat "${channel_file}"
