#!/usr/bin/env bash
# Reference invoice — every call of the xgenerate API against one template.
#
# Usage:
#   XGENERATE_CLIENT_ID=... XGENERATE_CLIENT_SECRET=... ./run.sh            # production
#   XGENERATE_BASE_URL=http://127.0.0.1:8200 XGENERATE_TOKEN= ./run.sh      # a local instance without auth
#
# Environment:
#   XGENERATE_BASE_URL       API base (default https://api.xgenerate.io/v2)
#   XGENERATE_TOKEN_URL      token endpoint (default the production realm)
#   XGENERATE_CLIENT_ID /
#   XGENERATE_CLIENT_SECRET  client-credentials grant; or set XGENERATE_TOKEN directly
#                            (empty XGENERATE_TOKEN + explicit XGENERATE_BASE_URL = no auth header)
#
# Runs from the directory holding this script and writes into ./out/.
# Requires curl, jq and base64. Exits non-zero on the first failed call and
# prints a final RESULT line.

set -euo pipefail

cd "$(dirname "$0")"
BASE_URL="${XGENERATE_BASE_URL:-https://api.xgenerate.io/v2}"
TOKEN_URL="${XGENERATE_TOKEN_URL:-https://auth.xgenerate.io/realms/xgenerate/protocol/openid-connect/token}"
TEMPLATE="Invoice-Form-A-CH-EN.docx"
OUT="out"
mkdir -p "$OUT"

for cmd in curl jq base64; do
  command -v "$cmd" >/dev/null 2>&1 || { echo "RESULT: FAIL — '$cmd' is required" >&2; exit 2; }
done

# ── 0. token ────────────────────────────────────────────────────────────────
if [ -z "${XGENERATE_TOKEN+x}" ]; then
  : "${XGENERATE_CLIENT_ID:?set XGENERATE_CLIENT_ID and XGENERATE_CLIENT_SECRET, or XGENERATE_TOKEN}"
  : "${XGENERATE_CLIENT_SECRET:?set XGENERATE_CLIENT_ID and XGENERATE_CLIENT_SECRET, or XGENERATE_TOKEN}"
  XGENERATE_TOKEN="$(curl -sS --fail-with-body -X POST "$TOKEN_URL" \
      -d grant_type=client_credentials \
      --data-urlencode "client_id=$XGENERATE_CLIENT_ID" \
      --data-urlencode "client_secret=$XGENERATE_CLIENT_SECRET" | jq -r .access_token)"
fi
# Without a token (local instance) no Authorization header is sent. The
# `${AUTH[@]+...}` form keeps `set -u` happy on bash 3.2 when the array is empty.
AUTH=()
if [ -n "$XGENERATE_TOKEN" ]; then
  AUTH=(-H "Authorization: Bearer $XGENERATE_TOKEN")
fi

step() { printf '\n== %s\n' "$*"; }

# ── 1. extract the field contract (multipart) ──────────────────────────────
step "1. POST /documents/fields — what the template needs"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} -F "file=@$TEMPLATE" \
  "$BASE_URL/documents/fields" > "$OUT/fields.extracted.json"
jq -r '"fields: \(.fields|length)  lists: \(.lists|length) (nested: \(.lists[0].value[0].lists|map(.name)|join(",")))  images: \(.images|map(.name)|join(","))  qrcodes: \(.qrcodes|map(.name)|join(","))  qrbills: \(.qrbills|map(.name)|join(","))  letterheads: \(.letterheads|map(.name)|join(","))"' "$OUT/fields.extracted.json"

# ── 2. computed bindings without a document ────────────────────────────────
step "2. POST /bindings/evaluate — line amounts and totals"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} -H 'Content-Type: application/json' \
  --data-binary @evaluate.request.json \
  "$BASE_URL/bindings/evaluate" > "$OUT/evaluated.json"
jq -r '.scalars | "subtotal \(.["invoice.subtotal"])  vat \(.["invoice.vatAmount"])  total \(.["invoice.total"])"' "$OUT/evaluated.json"

# ── 3. generate, multipart + sidecar (computed inside the call) ─────────────
step "3. POST /documents/generate — multipart with the sidecar, PDF"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} -D "$OUT/generate.headers" \
  -F "file=@$TEMPLATE" \
  -F "fields=@request.fields.json;type=application/json" \
  -F "sidecar=@sidecar.bindings.yaml;type=application/x-yaml" \
  -F "format=PDF" \
  "$BASE_URL/documents/generate" -o "$OUT/invoice.pdf"
grep -i '^content-disposition\|^x-xgenerate-warnings' "$OUT/generate.headers" || true
if grep -qi '^x-xgenerate-warnings:' "$OUT/generate.headers"; then
  grep -i '^x-xgenerate-warnings:' "$OUT/generate.headers" | sed 's/^[^:]*: *//' | tr -d '\r' | base64 --decode | jq .
fi

# ── 4. generate, JSON transport (values pre-computed in step 2) ────────────
step "4. POST /documents/generate — JSON with the evaluated values"
jq -n --rawfile tpl <(base64 < "$TEMPLATE" | tr -d '\n') \
      --slurpfile req request.fields.json --slurpfile ev "$OUT/evaluated.json" '
  ($ev[0].scalars) as $s
  | { filename: "Invoice-Form-A-CH-EN.docx", content: $tpl, format: "PDF",
      fields: ($req[0]
        | .fields |= map(if $s[.name] != null then .value = $s[.name] else . end)
        | .lists = $ev[0].lists) }' > "$OUT/generate.request.json"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} -H 'Content-Type: application/json' \
  --data-binary @"$OUT/generate.request.json" \
  "$BASE_URL/documents/generate" > "$OUT/generate.response.json"
jq -r '"filename \(.filename)  format \(.format)  warnings \(.warnings|length)"' "$OUT/generate.response.json"
jq -r .content "$OUT/generate.response.json" | base64 --decode > "$OUT/invoice-json.pdf"

# ── 5. DOCX output (editable; the QR-bill slip is PDF-only → one warning) ──
step "5. POST /documents/generate — DOCX"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} -D "$OUT/generate-docx.headers" \
  -F "file=@$TEMPLATE" \
  -F "fields=@request.fields.json;type=application/json" \
  -F "sidecar=@sidecar.bindings.yaml;type=application/x-yaml" \
  -F "format=DOCX" \
  "$BASE_URL/documents/generate" -o "$OUT/invoice.docx"
grep -i '^x-xgenerate-warnings-count' "$OUT/generate-docx.headers" || true

# ── 6. optional: watermark ─────────────────────────────────────────────────
step "6. POST /documents/generate — PDF with a SAMPLE watermark"
curl -sS --fail-with-body ${AUTH[@]+"${AUTH[@]}"} \
  -F "file=@$TEMPLATE" \
  -F "fields=@request.fields.json;type=application/json" \
  -F "sidecar=@sidecar.bindings.yaml;type=application/x-yaml" \
  -F "watermark=@watermark.json;type=application/json" \
  -F "format=PDF" \
  "$BASE_URL/documents/generate" -o "$OUT/invoice-sample.pdf"

for f in invoice.pdf invoice-json.pdf invoice-sample.pdf; do
  head -c 5 "$OUT/$f" | grep -q '%PDF-' || { echo "RESULT: FAIL — $OUT/$f is not a PDF" >&2; exit 1; }
done
echo
echo "RESULT: OK — see $OUT/ (invoice.pdf, invoice-json.pdf, invoice.docx, invoice-sample.pdf, fields.extracted.json, evaluated.json)"
