#!/usr/bin/env bash
#
# Notarize + staple a macOS artifact (a .app or a .dmg) with Apple's notary service.
#
#   scripts/notarize.sh <path-to-.app-or-.dmg>
#
# Notarization is Apple scanning the signed artifact and issuing a "ticket" that
# Gatekeeper trusts; stapling attaches that ticket so the artifact is trusted even
# offline. It REQUIRES the artifact to already be signed with a Developer ID identity,
# the hardened runtime, and a secure timestamp (scripts/package-app.sh does this when
# NUCLEIC_SIGN_ID is a real identity).
#
# notarytool needs a container, so a bare .app is zipped for submission, then the .app
# itself is stapled. A .dmg is submitted and stapled directly.
#
# Auth — two ways, resolved in this order (the API-key form is what CI uses):
#
#   1. Stored notary profile (recommended for local use). Create it once with:
#        xcrun notarytool store-credentials nucleic-notary \
#          --key   AuthKey_XXXX.p8 --key-id <KeyID> --issuer <IssuerID>
#      then run with NUCLEIC_NOTARY_PROFILE=nucleic-notary (the default below).
#
#   2. App Store Connect API key, passed by env (no keychain needed — for CI):
#        NUCLEIC_ASC_KEY_PATH=/path/AuthKey_XXXX.p8
#        NUCLEIC_ASC_KEY_ID=<KeyID>
#        NUCLEIC_ASC_ISSUER_ID=<IssuerID>

set -euo pipefail

ARTIFACT="${1:?usage: notarize.sh <path-to-.app-or-.dmg>}"
[ -e "$ARTIFACT" ] || { echo "notarize: no such path: $ARTIFACT" >&2; exit 2; }

PROFILE="${NUCLEIC_NOTARY_PROFILE:-nucleic-notary}"

# Build the notarytool auth arguments from whichever credential is available. Built straight into
# an array (no `mapfile` — that's a bash 4 builtin and macOS ships bash 3.2; and no function +
# process substitution, so the `exit 1` below actually aborts the script rather than a subshell).
AUTH=()
if [ -n "${NUCLEIC_ASC_KEY_PATH:-}" ] && [ -n "${NUCLEIC_ASC_KEY_ID:-}" ] && [ -n "${NUCLEIC_ASC_ISSUER_ID:-}" ]; then
  AUTH=(--key "$NUCLEIC_ASC_KEY_PATH" --key-id "$NUCLEIC_ASC_KEY_ID" --issuer "$NUCLEIC_ASC_ISSUER_ID")
elif xcrun notarytool history --keychain-profile "$PROFILE" >/dev/null 2>&1; then
  AUTH=(--keychain-profile "$PROFILE")
else
  cat >&2 <<EOF
notarize: no notary credentials found.

  • Local: create a stored profile once, then set NUCLEIC_NOTARY_PROFILE (default 'nucleic-notary'):
      xcrun notarytool store-credentials nucleic-notary --key AuthKey_XXXX.p8 --key-id <KeyID> --issuer <IssuerID>
  • CI:    export NUCLEIC_ASC_KEY_PATH / NUCLEIC_ASC_KEY_ID / NUCLEIC_ASC_ISSUER_ID
EOF
  exit 1
fi

submit() {  # submit <container> — submits and waits for Apple's verdict
  echo "▸ Submitting $(basename "$1") to Apple notary service (this can take a few minutes)…"
  xcrun notarytool submit "$1" "${AUTH[@]}" --wait
}

case "$ARTIFACT" in
  *.app)
    ZIP="${TMPDIR:-/tmp}/$(basename "$ARTIFACT" .app)-notarize.zip"
    echo "▸ Zipping app for submission → $ZIP"
    /usr/bin/ditto -c -k --keepParent "$ARTIFACT" "$ZIP"
    submit "$ZIP"
    rm -f "$ZIP"
    echo "▸ Stapling ticket to $ARTIFACT"
    xcrun stapler staple "$ARTIFACT"
    ;;
  *.dmg|*.pkg)
    submit "$ARTIFACT"
    echo "▸ Stapling ticket to $ARTIFACT"
    xcrun stapler staple "$ARTIFACT"
    ;;
  *)
    echo "notarize: unsupported artifact (expected .app, .dmg, or .pkg): $ARTIFACT" >&2
    exit 2
    ;;
esac

echo "▸ Verifying Gatekeeper acceptance"
case "$ARTIFACT" in
  *.app) spctl --assess --type exec --verbose=2 "$ARTIFACT" ;;
  *.dmg) spctl --assess --type open --context context:primary-signature --verbose=2 "$ARTIFACT" ;;
esac
xcrun stapler validate "$ARTIFACT"
echo "✓ Notarized + stapled: $ARTIFACT"
