#!/usr/bin/env bash
# Validate deck.module.json fixtures against spec/deck-module.schema.json via jq.
set -euo pipefail
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
SCHEMA="$ROOT/spec/deck-module.schema.json"
pass=0; fail=0
ok()  { echo "  PASS: $1"; pass=$((pass+1)); }
bad() { echo "  FAIL: $1"; fail=$((fail+1)); }

# jq validator mirroring spec/deck-module.schema.json (draft-07 contract).
validate_deck_module() {
  jq -e '
    def kebab: test("^[a-z][a-z0-9]*(-[a-z0-9]+)*$");
    def allowed: ["schema_version","name","kind","services","bootstrap","health","install","state_dirs"];
    def keys_ok: (keys - allowed | length) == 0;
    def valid_install:
      if has("install") then
        (.install | type == "object")
        and ((.install | keys - ["mode","needs_git"] | length) == 0)
        and (.install.mode | type == "string" and IN("in-place","artifact"))
        and (.install.needs_git | type == "boolean")
        and (.install | has("mode") and has("needs_git"))
      else true end;

    . as $doc
    | ($doc | type == "object")
    and ($doc | keys_ok)
    and ($doc | has("schema_version") and has("name") and has("kind"))
    and ($doc.schema_version | type == "number" and . == 1)
    and ($doc.name | type == "string" and kebab)
    and ($doc.kind | type == "string" and IN("service","cli","config","library"))
    and (if $doc | has("services") then
           ($doc.services | type == "array" and all(type == "string"))
         else true end)
    and (if $doc | has("bootstrap") then ($doc.bootstrap | type == "string") else true end)
    and (if $doc | has("health") then ($doc.health | type == "string") else true end)
    and ($doc | valid_install)
    and (if $doc | has("state_dirs") then
           ($doc.state_dirs | type == "array" and all(type == "string"))
         else true end)
  ' "$1" >/dev/null
}

expect_valid() {
  local label="$1" file="$2"
  if validate_deck_module "$file"; then ok "$label"; else bad "$label"; fi
}

expect_invalid() {
  local label="$1" file="$2"
  if validate_deck_module "$file" 2>/dev/null; then bad "$label (should reject)"; else ok "$label"; fi
}

FIX=$(mktemp -d "${TMPDIR:-/tmp}/schema-test-XXXXXX")
trap 'rm -rf "$FIX"' EXIT

[[ -f "$SCHEMA" ]] && ok "schema file exists" || bad "schema file missing"

cat >"$FIX/valid-full.json" <<'EOF'
{
  "schema_version": 1,
  "name": "harness",
  "kind": "service",
  "services": ["systemd/harnessd.service"],
  "bootstrap": "./bootstrap.sh",
  "health": "./health.sh",
  "install": { "mode": "artifact", "needs_git": true },
  "state_dirs": ["runstate", "tmp"]
}
EOF

cat >"$FIX/valid-minimal.json" <<'EOF'
{
  "schema_version": 1,
  "name": "monitor",
  "kind": "config"
}
EOF

cat >"$FIX/missing-schema-version.json" <<'EOF'
{
  "name": "harness",
  "kind": "service"
}
EOF

cat >"$FIX/bad-kind.json" <<'EOF'
{
  "schema_version": 1,
  "name": "harness",
  "kind": "daemon"
}
EOF

cat >"$FIX/extra-key.json" <<'EOF'
{
  "schema_version": 1,
  "name": "harness",
  "kind": "service",
  "version": 2
}
EOF

echo "=== valid fixtures ==="
expect_valid "full manifest (spec example)" "$FIX/valid-full.json"
expect_valid "minimal required fields" "$FIX/valid-minimal.json"

echo "=== invalid fixtures ==="
expect_invalid "missing schema_version" "$FIX/missing-schema-version.json"
expect_invalid "bad kind" "$FIX/bad-kind.json"
expect_invalid "extra key" "$FIX/extra-key.json"

echo "----"
echo "PASS=$pass FAIL=$fail"
[[ $fail -eq 0 ]]
