#!/usr/bin/env bash
# Durable per-component deployment convergence receipts.

component_receipt_path() {
  local component=$1
  [[ "$component" =~ ^[a-z0-9][a-z0-9-]*$ ]] || return 1
  printf '%s/%s.json\n' "$COMPONENT_RECEIPT_DIR" "$component"
}

component_receipt_sha() {
  local component=$1 path
  path=$(component_receipt_path "$component") || return 1
  [[ -f "$path" && ! -L "$path" ]] || return 1
  python3 - "$path" "$component" <<'PY'
import json
import re
import sys

path, expected = sys.argv[1:]
try:
    with open(path, "r", encoding="utf-8") as stream:
        value = json.load(stream)
except (OSError, ValueError):
    raise SystemExit(1)
sha = value.get("target_sha") if isinstance(value, dict) else None
good = (
    value.get("schema") == 1
    and value.get("component") == expected
    and isinstance(sha, str)
    and re.fullmatch(r"[0-9a-f]{40}", sha) is not None
)
if not good:
    raise SystemExit(1)
print(sha)
PY
}

component_convergence_base() (
  local component=$1 fallback=$2 target=$3 receipt="" base="" candidate
  cd "$DEPLOY" 2>/dev/null || return 1
  [[ "$target" =~ ^[0-9a-f]{40}$ ]] || return 1
  git cat-file -e "${target}^{commit}" 2>/dev/null || return 1
  receipt=$(component_receipt_sha "$component" 2>/dev/null || true)
  for candidate in "$receipt" "$fallback"; do
    [[ "$candidate" =~ ^[0-9a-f]{40}$ ]] || continue
    git cat-file -e "${candidate}^{commit}" 2>/dev/null || continue
    git merge-base --is-ancestor "$candidate" "$target" 2>/dev/null || continue
    if [[ -z "$base" ]]; then
      base=$candidate
    elif git merge-base --is-ancestor "$base" "$candidate" 2>/dev/null; then
      base=$candidate
    elif ! git merge-base --is-ancestor "$candidate" "$base" 2>/dev/null; then
      return 1
    fi
  done
  [[ -n "$base" ]] || return 1
  printf '%s\n' "$base"
)

publish_component_receipt() {
  local component=$1 target=$2 path tmp converged_at
  [[ "$target" =~ ^[0-9a-f]{40}$ ]] || return 1
  path=$(component_receipt_path "$component") || return 1
  mkdir -p "$COMPONENT_RECEIPT_DIR" || return 1
  [[ ! -L "$path" && ( ! -e "$path" || -f "$path" ) ]] || return 1
  tmp=$(mktemp "$COMPONENT_RECEIPT_DIR/.${component}.json.XXXXXX") || return 1
  converged_at="${OVERDECK_COMPONENT_RECEIPT_NOW:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}"
  if ! printf '{"schema":1,"component":"%s","target_sha":"%s","converged_at":"%s"}\n' \
      "$component" "$target" "$converged_at" >"$tmp" \
    || ! chmod 0644 "$tmp" \
    || ! mv -fT "$tmp" "$path"; then
    rm -f "$tmp"
    return 1
  fi
}
