#!/usr/bin/env bash
# Fixture test for bin/deckctl dispatcher + doctor + status (fail-closed).
set -euo pipefail
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
DECKCTL="$ROOT/bin/deckctl"
FIX=$(mktemp -d "${TMPDIR:-/tmp}/deckctl-core-test-XXXXXX")
trap 'rm -rf "$FIX"' EXIT
pass=0; fail=0
ok()  { echo "  PASS: $1"; pass=$((pass+1)); }
bad() { echo "  FAIL: $1"; fail=$((fail+1)); }

mk_sandbox() { # $1=dest
  local dest="$1"
  mkdir -p "$dest/spec" "$dest/modules" "$dest/bin" "$dest/lib/deckctl"
  cp "$ROOT/spec/deck-module.schema.json" "$dest/spec/"
  cp "$ROOT/bin/deckctl" "$dest/bin/"
  cp "$ROOT/lib/deckctl/doctor.sh" "$dest/lib/deckctl/"
  cp "$ROOT/lib/deckctl/status.sh" "$dest/lib/deckctl/"
}

mk_valid_module() { # $1=sandbox $2=name
  local sb="$1" name="$2"
  local mdir="$sb/modules/$name"
  mkdir -p "$mdir"
  cat >"$mdir/deck.module.json" <<EOF
{
  "schema_version": 1,
  "name": "$name",
  "kind": "cli",
  "bootstrap": "./bootstrap.sh",
  "health": "./health.sh",
  "install": { "mode": "in-place", "needs_git": false }
}
EOF
  printf '#!/usr/bin/env bash\nexit 0\n' >"$mdir/bootstrap.sh"
  printf '#!/usr/bin/env bash\nexit 0\n' >"$mdir/health.sh"
  chmod +x "$mdir/bootstrap.sh" "$mdir/health.sh"
}

run_deckctl() { # $1=sandbox $2+=args
  local sb="$1"; shift
  HOME="${TEST_HOME:-$FIX/home}" "$sb/bin/deckctl" "$@"
}

export TEST_HOME="$FIX/home"
mkdir -p "$TEST_HOME/.local/opt/overdeck" "$TEST_HOME/.local/state/overdeck"

echo "=== prereq: scripts exist ==="
for f in "$DECKCTL" "$ROOT/lib/deckctl/doctor.sh" "$ROOT/lib/deckctl/status.sh"; do
  [[ -f "$f" ]] && ok "$(basename "$f") exists" || bad "missing $f"
done

echo "=== bash -n clean ==="
for f in "$DECKCTL" "$ROOT/lib/deckctl/doctor.sh" "$ROOT/lib/deckctl/status.sh"; do
  bash -n "$f" && ok "bash -n $(basename "$f")" || bad "bash -n $(basename "$f")"
done

echo "=== unknown subcommand exits 2 ==="
set +e
out=$(run_deckctl "$ROOT" nosuchcmd 2>&1)
rc=$?
set -e
if [[ $rc -eq 2 ]]; then ok "unknown subcommand exits 2"; else bad "unknown subcommand rc=$rc (want 2)"; fi
if printf '%s\n' "$out" | grep -qi usage; then ok "unknown subcommand prints usage"; else bad "no usage message"; fi

echo "=== valid fixture module: doctor exits 0 ==="
SB="$FIX/sb-valid"
mk_sandbox "$SB"
mk_valid_module "$SB" fixture
set +e
out=$(run_deckctl "$SB" doctor 2>&1)
rc=$?
set -e
if [[ $rc -eq 0 ]]; then ok "doctor valid module exits 0"; else bad "doctor valid module rc=$rc: $out"; fi

echo "=== broken manifest: doctor exits 1 naming module ==="
SB="$FIX/sb-broken"
mk_sandbox "$SB"
mkdir -p "$SB/modules/broken"
cat >"$SB/modules/broken/deck.module.json" <<'EOF'
{
  "schema_version": 1,
  "name": "broken",
  "kind": "daemon"
}
EOF
set +e
out=$(run_deckctl "$SB" doctor 2>&1)
rc=$?
set -e
if [[ $rc -eq 1 ]]; then ok "doctor broken manifest exits 1"; else bad "doctor broken manifest rc=$rc (want 1)"; fi
if printf '%s\n' "$out" | grep -q 'broken'; then ok "doctor names broken module"; else bad "doctor output missing module name: $out"; fi

echo "=== status always exits 0 ==="
SB="$FIX/sb-status"
mk_sandbox "$SB"
mk_valid_module "$SB" fixture
set +e
out=$(run_deckctl "$SB" status 2>&1)
rc=$?
set -e
if [[ $rc -eq 0 ]]; then ok "status exits 0"; else bad "status rc=$rc"; fi
if printf '%s\n' "$out" | grep -q 'fixture'; then ok "status lists fixture module"; else bad "status missing fixture: $out"; fi

echo "=== dangling symlink reported by doctor ==="
SB="$FIX/sb-dangle"
mk_sandbox "$SB"
mk_valid_module "$SB" fixture
ln -s /nonexistent/target "$TEST_HOME/.local/opt/overdeck/dangle-link"
set +e
out=$(run_deckctl "$SB" doctor 2>&1)
rc=$?
set -e
if [[ $rc -eq 1 ]]; then ok "doctor reports dangling symlink (exit 1)"; else bad "doctor dangling symlink rc=$rc"; fi
if printf '%s\n' "$out" | grep -q 'dangle-link'; then ok "doctor names dangling symlink"; else bad "dangling symlink not named: $out"; fi

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