#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

usage() {
  cat <<'EOF'
Usage: Scripts/seal-release-secrets.sh [--source-dir <dir>] [--only <secret>]

Encrypt Burrow release inputs into the agenix secrets consumed by CI.

Expected files in --source-dir (default: intake/release):
  appstore-key-id.txt
  appstore-key-issuer-id.txt
  appstore-key.p8
  distribution-cert.p12
  distribution-cert-password.txt
  sparkle-eddsa.key

Pre-composed appstore-connect.env, distribution-signing.env, and sparkle.env
files are also accepted.

Provisioning profiles are synced from App Store Connect credentials in CI.
The temporary keychain password is always the distribution certificate password.

Secrets:
  all
  appstore-connect
  distribution-signing
  sparkle
EOF
}

SOURCE_DIR="${BURROW_RELEASE_SECRET_SOURCE_DIR:-${REPO_ROOT}/intake/release}"
ONLY="all"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --source-dir)
      SOURCE_DIR="${2:?missing value for --source-dir}"
      shift 2
      ;;
    --only)
      ONLY="${2:?missing value for --only}"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown option: $1" >&2
      usage >&2
      exit 64
      ;;
  esac
done

case "$ONLY" in
  all|appstore-connect|app-store|appstore|distribution-signing|apple-signing|sparkle) ;;
  *)
    echo "unknown release secret selector: $ONLY" >&2
    usage >&2
    exit 64
    ;;
esac

require_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "missing required command: $1" >&2
    exit 1
  fi
}

require_cmd age
require_cmd nix
require_cmd python3

if [[ ! -d "$SOURCE_DIR" ]]; then
  echo "release secret source directory does not exist: $SOURCE_DIR" >&2
  exit 1
fi

tmpdir="$(mktemp -d)"
cleanup() {
  rm -rf "$tmpdir"
}
trap cleanup EXIT

seal_secret() {
  local target="$1"
  local source_path="$2"
  local required="${3:-required}"
  local recipients_file="${tmpdir}/$(basename "${target}").recipients"

  if [[ ! -s "$source_path" ]]; then
    if [[ "$required" == "optional" ]]; then
      return 0
    fi
    echo "required release secret source missing or empty: $source_path" >&2
    exit 1
  fi

  mkdir -p "${REPO_ROOT}/$(dirname "$target")"
  nix eval --impure --json --expr "let s = import ${REPO_ROOT}/secrets.nix; in s.\"${target}\".publicKeys" \
    | python3 -c 'import json, sys; [print(item) for item in json.load(sys.stdin)]' \
    > "$recipients_file"

  age -R "$recipients_file" -o "${REPO_ROOT}/${target}" "$source_path"
  chmod 600 "${REPO_ROOT}/${target}"
  echo "Sealed ${target}"
}

base64_file() {
  python3 -c 'import base64, pathlib, sys; print(base64.b64encode(pathlib.Path(sys.argv[1]).read_bytes()).decode())' "$1"
}

read_secret_text() {
  python3 -c 'import pathlib, sys; sys.stdout.write(pathlib.Path(sys.argv[1]).read_text().strip())' "$1"
}

base64_text() {
  python3 -c 'import base64, sys; print(base64.b64encode(sys.stdin.buffer.read()).decode())'
}

reject_placeholder() {
  local path="$1"
  if grep -Eq '^(TODO|PASTE_|REPLACE_|#)' "$path"; then
    echo "intake file still contains placeholder text: $path" >&2
    exit 1
  fi
}

reject_placeholder_text() {
  local path="$1"
  if grep -Iq . "$path"; then
    reject_placeholder "$path"
  fi
}

first_existing() {
  local path
  for path in "$@"; do
    if [[ -s "$path" ]]; then
      printf '%s\n' "$path"
      return 0
    fi
  done
  return 1
}

compose_appstore_connect_env() {
  local direct="${SOURCE_DIR}/appstore-connect.env"
  if [[ -s "$direct" ]]; then
    printf '%s\n' "$direct"
    return 0
  fi

  local key_id_file="${SOURCE_DIR}/appstore-key-id.txt"
  local issuer_id_file="${SOURCE_DIR}/appstore-key-issuer-id.txt"
  local key_file="${SOURCE_DIR}/appstore-key.p8"
  if [[ ! -s "$key_file" ]]; then
    echo "required App Store Connect source missing or empty: appstore-key.p8" >&2
    exit 1
  fi
  for path in "$key_id_file" "$issuer_id_file" "$key_file"; do
    if [[ ! -s "$path" ]]; then
      echo "required App Store Connect source missing or empty: $path" >&2
      exit 1
    fi
    reject_placeholder_text "$path"
  done

  local out="${tmpdir}/appstore-connect.env"
  {
    printf 'ASC_API_KEY_ID=%s\n' "$(read_secret_text "$key_id_file")"
    printf 'ASC_API_ISSUER_ID=%s\n' "$(read_secret_text "$issuer_id_file")"
    printf 'ASC_API_KEY_BASE64=%s\n' "$(base64_file "$key_file")"
  } > "$out"
  printf '%s\n' "$out"
}

compose_distribution_signing_env() {
  local direct="${SOURCE_DIR}/distribution-signing.env"
  if [[ -s "$direct" ]]; then
    printf '%s\n' "$direct"
    return 0
  fi

  local cert_file
  cert_file="${SOURCE_DIR}/distribution-cert.p12"
  local password_file="${SOURCE_DIR}/distribution-cert-password.txt"
  if [[ ! -s "$cert_file" ]]; then
    echo "required distribution signing source missing or empty: distribution-cert.p12" >&2
    exit 1
  fi
  for path in "$password_file"; do
    if [[ ! -s "$path" ]]; then
      echo "required distribution signing source missing or empty: $path" >&2
      exit 1
    fi
    reject_placeholder_text "$path"
  done

  local out="${tmpdir}/distribution-signing.env"
  {
    printf 'APPLE_SIGNING_CERTIFICATE_BASE64=%s\n' "$(base64_file "$cert_file")"
    printf 'APPLE_SIGNING_CERTIFICATE_PASSWORD_BASE64=%s\n' "$(read_secret_text "$password_file" | base64_text)"
  } > "$out"
  printf '%s\n' "$out"
}

compose_sparkle_env() {
  local direct="${SOURCE_DIR}/sparkle.env"
  if [[ -s "$direct" ]]; then
    printf '%s\n' "$direct"
    return 0
  fi

  local key_file
  key_file="${SOURCE_DIR}/sparkle-eddsa.key"
  if [[ ! -s "$key_file" ]]; then
    return 1
  fi
  reject_placeholder_text "$key_file"

  local out="${tmpdir}/sparkle.env"
  printf 'SPARKLE_EDDSA_KEY_BASE64=%s\n' "$(base64_file "$key_file")" > "$out"
  printf '%s\n' "$out"
}

case "$ONLY" in
  all)
    appstore_env="$(compose_appstore_connect_env)"
    seal_secret "secrets/apple/appstore-connect.env.age" "$appstore_env"
    distribution_env="$(compose_distribution_signing_env)"
    seal_secret "secrets/apple/distribution-signing.env.age" "$distribution_env"
    if sparkle_env="$(compose_sparkle_env)"; then
      seal_secret "secrets/apple/sparkle.env.age" "$sparkle_env"
    fi
    ;;
  appstore-connect|app-store|appstore)
    appstore_env="$(compose_appstore_connect_env)"
    seal_secret "secrets/apple/appstore-connect.env.age" "$appstore_env"
    ;;
  distribution-signing|apple-signing)
    distribution_env="$(compose_distribution_signing_env)"
    seal_secret "secrets/apple/distribution-signing.env.age" "$distribution_env"
    ;;
  sparkle)
    if sparkle_env="$(compose_sparkle_env)"; then
      seal_secret "secrets/apple/sparkle.env.age" "$sparkle_env"
    else
      echo "required Sparkle source missing or empty: sparkle-eddsa.key" >&2
      exit 1
    fi
    ;;
esac

echo "Release secrets are sealed. Commit the .age files and deploy/use CI with an authorized age identity."
