#!/usr/bin/env bash
# cf-schema-check.sh - canonical acceptance-schema validator.
#
# The document-acceptance store (e-sign / works-agreement / quote-signing
# watchers) has ONE canonical shape, declared in
# references/d1-data-capture.md § The canonical acceptance store. This helper is
# the exit-code gate that confirms a live store follows it, so a watcher can
# rely on reading one known shape instead of three drifted ones.
#
# Input:  stdin = the DDL text `wrangler d1 execute <db> --remote --command
#         "SELECT sql FROM sqlite_master;"` returns (the SQLite-stored CREATE
#         statements). This is machine-generated DDL, not prose, so token
#         inspection is a deterministic pre-flight.
# Output: stdout = nothing on success. stderr = a [cf-schema-check] line naming
#         the first failing check.
# Exit:   0 iff the input matches the canonical acceptance shape; 1 on any drift.
set -u

fail() { echo "[cf-schema-check] drift: $*" >&2; exit 1; }

ddl="$(cat)"
has() { printf '%s' "$ddl" | grep -Eiq "$1"; }

# 1. An `acceptances` table must exist. \bacceptances\b does not match inside
#    `dual_acceptances` (the underscore suppresses the word boundary), so this
#    is specific to the canonical table.
has 'create table[^;(]*\bacceptances\b' || fail "no acceptances table in the store"

# 2. No `dual_acceptances` table. Its presence is the two-signer sprawl the
#    canonical `party` column replaces. Checked against the whole dump.
has '\bdual_acceptances\b' && fail "stray dual_acceptances table (use the party column, not a second table)"

# Isolate the `acceptances` CREATE statement so column checks are scoped to it,
# not bled across sibling tables (a leads table's `swept` must not satisfy the
# acceptances requirement). Print from the acceptances CREATE line to its `);`.
acc="$(printf '%s\n' "$ddl" | awk '
  { l = tolower($0) }
  l ~ /create table/ && l ~ /acceptances/ && l !~ /dual_acceptances/ { f = 1 }
  f { print }
  f && /\);/ { exit }
')"
hasin() { printf '%s' "$acc" | grep -Eiq "$1"; }

# 3. The signer column is `signer_name`, never a bare `name`. \bname\b does not
#    match inside `signer_name`, so a standalone `name` token with no
#    `signer_name` present is the drift signature.
if ! hasin '\bsigner_name\b'; then
  if hasin '\bname\b'; then
    fail "signer column is bare 'name', expected 'signer_name'"
  fi
  fail "missing required column: signer_name"
fi

# 4. Every canonical column present in the acceptances table. signer_name is
#    already confirmed above.
for col in doc_ref doc_type party accepted_at swept; do
  hasin "\\b${col}\\b" || fail "missing required column: ${col}"
done

exit 0
