#!/usr/bin/env sh
set -eu

# PPE E2E content seed (§9 deployed-environment harness).
#
# The Tier-1 docker seed (seed-gitea.sh) stands up a throwaway Gitea. PPE
# instead runs against the REAL Gitea (git.wiggleverse.org) — which it
# shares with prod. To exercise the §22.4a metadata UI (faceted filter
# SLICE-3, edit panel SLICE-4, bulk bar SLICE-5) on PPE WITHOUT touching
# real OHM content, this script seeds a DEDICATED, PPE-only registry +
# content repo:
#
#   wiggleverse/rfc-registry-ppe   — PPE's own project registry (prod
#                                    keeps using wiggleverse/rfc-registry,
#                                    so prod is never affected).
#   wiggleverse/rfc-app-ppe-content — content for the one project the PPE
#                                    registry describes: a default
#                                    (document) collection + a faceted
#                                    `bdd` named collection with a
#                                    fields: schema + three entries.
#
# Point PPE at the PPE registry with:
#     flotilla-core overlay set rfc-app-ppe REGISTRY_REPO=rfc-registry-ppe
# The app's startup reconciler sweep loads this content into cached_rfcs
# on the next deploy/restart (no webhook needed for the initial load).
#
# Auth: pass a Gitea token with org repo-create + content-write scope via
# GITEA_TOKEN (the wiggleverse admin token — see the wgl-gitea-admin
# skill; never echo it). The collection path the E2E suite hits is
# /p/ohm/c/bdd, so the seeded project id is `ohm` (matching the Tier-1
# seed and DEFAULT_PROJECT_ID=ohm) and the collection is `bdd`.
#
# Idempotent: repos/files that already exist are left as-is. Pass
# RESEED=1 to force-overwrite the three entry files back to their seed
# values (so a re-run restores SLICE-4/5's expected preconditions).

GITEA="${GITEA_URL:-https://git.wiggleverse.org}"
ORG="${GITEA_ORG:-wiggleverse}"
REGISTRY_REPO="${REGISTRY_REPO:-rfc-registry-ppe}"
CONTENT_REPO="${CONTENT_REPO:-rfc-app-ppe-content}"
PROJECT_ID="${DEFAULT_PROJECT_ID:-ohm}"
TOKEN="${GITEA_TOKEN:?set GITEA_TOKEN to a wiggleverse-org admin/bot token (do not echo it)}"
RESEED="${RESEED:-0}"

api() { curl -s -H "Authorization: token $TOKEN" "$@"; }

# mutate <method> <url> <json> <ok_code> <label>
# Performs an authenticated write and FAILS LOUDLY on any non-<ok_code>
# response. `api` uses `curl -s` (no -f), so without this a 403/409/etc.
# returns exit 0 with an error JSON body — which once let a swallowed 403
# (org-repo create needs write:organization) sail past as "created…" and
# only surfaced as a 502 at deploy time. Never let an HTTP error be silent.
mutate() {
  _m="$1"; _u="$2"; _d="$3"; _ok="$4"; _lbl="$5"
  _resp=$(api -X "$_m" "$_u" -H 'Content-Type: application/json' -d "$_d" -w '\n%{http_code}')
  _code=$(printf '%s' "$_resp" | tail -n1)
  if [ "$_code" != "$_ok" ]; then
    echo "seed-ppe: $_lbl FAILED (http $_code): $(printf '%s' "$_resp" | sed '$d' | head -c 300)" >&2
    exit 1
  fi
}

echo "seed-ppe: target $GITEA org=$ORG registry=$REGISTRY_REPO content=$CONTENT_REPO project=$PROJECT_ID"

ensure_repo() {
  if api -o /dev/null -w '%{http_code}' "$GITEA/api/v1/repos/$ORG/$1" | grep -q '^200$'; then
    echo "seed-ppe: repo $ORG/$1 exists"
    return 0
  fi
  echo "seed-ppe: creating repo $ORG/$1 (private)"
  mutate POST "$GITEA/api/v1/orgs/$ORG/repos" \
    "{\"name\":\"$1\",\"auto_init\":true,\"default_branch\":\"main\",\"private\":true}" \
    201 "create repo $ORG/$1 (org-repo create needs a write:organization token)"
}

# file_sha <repo> <path> -> prints the blob sha if the file exists, else empty
file_sha() {
  api "$GITEA/api/v1/repos/$ORG/$1/contents/$2?ref=main" \
    | sed -n 's/.*"sha":"\([0-9a-f]*\)".*/\1/p' | head -1
}

# put_file <repo> <path> <plaintext> [force]
# Creates the file if absent. If it exists: skipped, unless force=1, in
# which case it is updated in place (PUT with the current sha).
put_file() {
  _repo="$1"; _path="$2"; _content="$3"; _force="${4:-0}"
  _b64=$(printf '%s' "$_content" | base64 | tr -d '\n')
  _sha=$(file_sha "$_repo" "$_path")
  if [ -n "$_sha" ]; then
    if [ "$_force" = "1" ]; then
      echo "seed-ppe: updating $_repo/$_path"
      mutate PUT "$GITEA/api/v1/repos/$ORG/$_repo/contents/$_path" \
        "{\"message\":\"reseed $_path\",\"content\":\"$_b64\",\"sha\":\"$_sha\",\"branch\":\"main\"}" \
        200 "update $_repo/$_path"
    else
      echo "seed-ppe: $_repo/$_path exists, leaving as-is"
    fi
    return 0
  fi
  echo "seed-ppe: creating $_repo/$_path"
  mutate POST "$GITEA/api/v1/repos/$ORG/$_repo/contents/$_path" \
    "{\"message\":\"seed $_path\",\"content\":\"$_b64\",\"branch\":\"main\"}" \
    201 "create $_repo/$_path"
}

# delete_file <repo> <path> — remove the file if it exists (no-op if absent).
delete_file() {
  _repo="$1"; _path="$2"
  _sha=$(file_sha "$_repo" "$_path")
  [ -n "$_sha" ] || { echo "seed-ppe: $_repo/$_path absent, nothing to delete"; return 0; }
  echo "seed-ppe: deleting $_repo/$_path"
  mutate DELETE "$GITEA/api/v1/repos/$ORG/$_repo/contents/$_path" \
    "{\"message\":\"reseed: drop sidecar $_path\",\"sha\":\"$_sha\",\"branch\":\"main\"}" \
    200 "delete $_repo/$_path"
}

ensure_repo "$REGISTRY_REPO"
ensure_repo "$CONTENT_REPO"

# The PPE registry describes a single project `ohm` whose content lives in
# the dedicated PPE content repo.
put_file "$REGISTRY_REPO" "projects.yaml" "deployment:
  name: RFC PPE
  tagline: rfc-app pre-prod (E2E fixtures)
projects:
  - id: $PROJECT_ID
    name: OHM
    type: document
    content_repo: $CONTENT_REPO
    visibility: public
"

# Default (document) collection — one entry under rfcs/.
put_file "$CONTENT_REPO" "rfcs/intro.md" "---
slug: intro
title: Intro
state: active
id: RFC-0001
owners: [ben.stull]
---

# Intro

Seed entry for the default (document) collection on PPE.
"

# Faceted named collection 'bdd' with a fields: schema (§22.4a).
put_file "$CONTENT_REPO" "bdd/.collection.yaml" "type: bdd
visibility: public
name: BDD Scenarios
fields:
  priority:
    type: enum
    values: [P0, P1, P2]
    label: Priority
  tags:
    type: tags
    label: Tags
"

# Three entries with varied priority/tags so facets have counts and the
# bulk bar has multiple selectable rows. Force-overwritten when RESEED=1
# so a re-run restores SLICE-4 (checkout-returning starts P1) and SLICE-5
# (two P0 entries) preconditions.
put_file "$CONTENT_REPO" "bdd/rfcs/checkout-guest.md" "---
slug: checkout-guest
title: Guest checkout
state: active
priority: P0
tags: [checkout, payments]
---

Guest checkout scenario.
" "$RESEED"
put_file "$CONTENT_REPO" "bdd/rfcs/checkout-returning.md" "---
slug: checkout-returning
title: Returning-customer checkout
state: active
priority: P1
tags: [checkout]
---

Returning-customer checkout scenario.
" "$RESEED"
put_file "$CONTENT_REPO" "bdd/rfcs/search-facets.md" "---
slug: search-facets
title: Faceted search
state: active
priority: P0
tags: [search]
---

Faceted search scenario.
" "$RESEED"

# RESEED also drops any metadata sidecars (<slug>.meta.yaml) left by prior
# SLICE-4/5 edits. A sidecar takes precedence over the .md frontmatter
# (dual-read, §22.4a), so without this a re-run inherits the edited
# priorities (everything ends up P1) and the faceted preconditions drift —
# SLICE-3 expects P0 count = 2. Dropping the sidecars restores the
# frontmatter as the source of truth: checkout-guest=P0, search-facets=P0,
# checkout-returning=P1.
if [ "$RESEED" = "1" ]; then
  for _slug in checkout-guest checkout-returning search-facets; do
    delete_file "$CONTENT_REPO" "bdd/rfcs/$_slug.meta.yaml"
  done
fi

echo "seed-ppe: done. Set REGISTRY_REPO=$REGISTRY_REPO on rfc-app-ppe and redeploy."
