#!/usr/bin/env bash
# Tests for `shenron endpoint setup` and `shenron endpoint teardown` (offline / unit-level).
# Uses a mock HTTP server so no real Cloudflare token is needed.
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

if ! command -v shenron >/dev/null 2>&1; then
  echo "shenron CLI not available; install the local package first (for example: python3 -m pip install -e \"$ROOT_DIR\")" >&2
  exit 1
fi

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
die() { echo "FAIL: $*" >&2; exit 1; }
pass() { echo "PASS: $*"; }

tmpdir="$(mktemp -d)"
cleanup() { rm -rf "$tmpdir"; kill "$MOCK_PID" 2>/dev/null || true; }
trap cleanup EXIT

# Start mock CF server
MOCK_PORT=19988
python3 "$ROOT_DIR/tests/mock_cf_server.py" "$MOCK_PORT" &
MOCK_PID=$!
sleep 0.4  # let it bind

# ---------------------------------------------------------------------------
# Test: already-configured short-circuit (no --reset)
# ---------------------------------------------------------------------------
meta_dir="$tmpdir/already/.generated"
mkdir -p "$meta_dir"
cat > "$meta_dir/node_endpoint.json" <<'EOF'
{
  "fqdn": "node-aabbccdd.nodes.doubleword.ai",
  "subdomain_label": "node-aabbccdd",
  "base_domain": "nodes.doubleword.ai",
  "public_ip": "1.2.3.4",
  "cloudflare_zone_id": "zone123",
  "cloudflare_record_id": "rec456",
  "created_at": "2025-01-01T00:00:00+00:00"
}
EOF

output="$(shenron endpoint setup --output-dir "$tmpdir/already" 2>&1)"
echo "$output" | grep -q "already configured" \
  || die "expected 'already configured' message, got: $output"
pass "no-reset short-circuits with 'already configured'"

# ---------------------------------------------------------------------------
# Test: 'shenron endpoint' with no sub-command prints usage to stderr
# ---------------------------------------------------------------------------
if shenron endpoint 2>/dev/null; then
  die "'shenron endpoint' with no sub-command should exit non-zero"
fi
usage_output="$(shenron endpoint 2>&1 || true)"
echo "$usage_output" | grep -q "usage:" \
  || die "expected usage line, got: $usage_output"
pass "'shenron endpoint' (no sub-command) exits non-zero and prints usage"

# ---------------------------------------------------------------------------
# Test: 'shenron endpoint setup --help' exits 0 and mentions --slug
# ---------------------------------------------------------------------------
help_output="$(shenron endpoint setup --help 2>&1 || true)"
echo "$help_output" | grep -q -- "--slug" \
  || die "--help output missing --slug, got: $help_output"
pass "'shenron endpoint setup --help' shows --slug"

# ---------------------------------------------------------------------------
# Test: --base-domain flag is no longer accepted (baked into binary)
# ---------------------------------------------------------------------------
base_domain_out="$(
  shenron endpoint setup --base-domain example.com --public-ip 1.2.3.4 \
    --slug test-node --cf-token fake --output-dir "$tmpdir/bd" 2>&1 || true
)"
echo "$base_domain_out" | grep -iq "unrecognized\|error\|invalid" \
  || die "expected error for --base-domain flag, got: $base_domain_out"
pass "--base-domain flag is rejected (no longer accepted)"

# ---------------------------------------------------------------------------
# Test: invalid IPv4 rejected
# ---------------------------------------------------------------------------
invalid_ip_out="$(
  SHENRON_CF_API_URL="http://127.0.0.1:${MOCK_PORT}" \
  shenron endpoint setup \
      --slug test-node \
      --public-ip not-an-ip \
      --cf-token fake-token \
      --output-dir "$tmpdir/badip" 2>&1 || true
)"
echo "$invalid_ip_out" | grep -iq "invalid\|error" \
  || die "expected error for invalid IP, got: $invalid_ip_out"
pass "invalid IPv4 address is rejected"

# ---------------------------------------------------------------------------
# Test: invalid slug rejected (capital letters)
# ---------------------------------------------------------------------------
invalid_slug_out="$(
  SHENRON_CF_API_URL="http://127.0.0.1:${MOCK_PORT}" \
  shenron endpoint setup \
      --slug "BadSlug" \
      --public-ip 1.2.3.4 \
      --cf-token fake-token \
      --output-dir "$tmpdir/badslug" 2>&1 || true
)"
echo "$invalid_slug_out" | grep -iq "invalid\|error" \
  || die "expected error for invalid slug, got: $invalid_slug_out"
pass "invalid slug is rejected"

# ---------------------------------------------------------------------------
# Test: teardown refuses to delete records outside *.nodes.doubleword.ai
# ---------------------------------------------------------------------------
bad_meta_dir="$tmpdir/badmeta/.generated"
mkdir -p "$bad_meta_dir"
cat > "$bad_meta_dir/node_endpoint.json" <<'EOF'
{
  "fqdn": "evil.doubleword.ai",
  "subdomain_label": "evil",
  "base_domain": "doubleword.ai",
  "public_ip": "9.9.9.9",
  "cloudflare_zone_id": "zone999",
  "cloudflare_record_id": "rec999",
  "created_at": "2025-01-01T00:00:00+00:00"
}
EOF
guard_out="$(
  SHENRON_CF_API_URL="http://127.0.0.1:${MOCK_PORT}" \
  shenron endpoint teardown --yes \
      --cf-token fake-token \
      --output-dir "$tmpdir/badmeta" 2>&1 || true
)"
echo "$guard_out" | grep -iq "security\|restricted\|violation" \
  || die "expected security guard error for out-of-domain fqdn, got: $guard_out"
pass "teardown refuses to delete records outside *.nodes.doubleword.ai"

# ---------------------------------------------------------------------------
# Test: teardown with valid metadata deletes record and removes metadata file
# ---------------------------------------------------------------------------
good_meta_dir="$tmpdir/goodmeta/.generated"
mkdir -p "$good_meta_dir"
cat > "$good_meta_dir/node_endpoint.json" <<'EOF'
{
  "fqdn": "node-test01.nodes.doubleword.ai",
  "subdomain_label": "node-test01",
  "base_domain": "nodes.doubleword.ai",
  "public_ip": "1.2.3.4",
  "cloudflare_zone_id": "fake-zone-id",
  "cloudflare_record_id": "fake-record-id",
  "created_at": "2025-01-01T00:00:00+00:00"
}
EOF
teardown_out="$(
  SHENRON_CF_API_URL="http://127.0.0.1:${MOCK_PORT}" \
  shenron endpoint teardown --yes \
      --cf-token fake-token \
      --output-dir "$tmpdir/goodmeta" 2>&1
)"
echo "$teardown_out" | grep -iq "torn down\|deleted" \
  || die "expected success message from teardown, got: $teardown_out"
[[ ! -f "$good_meta_dir/node_endpoint.json" ]] \
  || die "expected metadata file to be removed after teardown"
pass "teardown deletes CF record and removes metadata file"

# ---------------------------------------------------------------------------
# Test: teardown with no metadata returns a clear error
# ---------------------------------------------------------------------------
no_meta_out="$(
  shenron endpoint teardown --yes --cf-token fake \
      --output-dir "$tmpdir/nometa" 2>&1 || true
)"
echo "$no_meta_out" | grep -iq "no endpoint metadata\|nothing to tear" \
  || die "expected 'no endpoint metadata' error, got: $no_meta_out"
pass "teardown with no metadata gives clear error"

echo "All endpoint setup/teardown tests passed."
