#!/usr/bin/env bash
# M7.1 tenant-gating smoke test.
#
# Drives compliance-smoke against a live Keycloak realm with five test
# users (one per tenant_status), asserts the response code on each
# endpoint, and exits non-zero on any mismatch.
#
# Pre-reqs (one-time):
#   * KC up at $KC_URL with realm $KC_REALM
#   * Client $KC_CLIENT has direct-access-grants enabled
#   * Users + tenant_status mappers per certifai/keycloak/realm-export.json
#   * compliance-smoke binary running and reachable at $SMOKE_URL
#
# Usage:
#   scripts/smoke.sh              # uses defaults below
#   SMOKE_URL=... scripts/smoke.sh

set -euo pipefail

KC_URL="${KC_URL:-http://localhost:8080}"
KC_REALM="${KC_REALM:-certifai}"
KC_CLIENT="${KC_CLIENT:-certifai-dashboard}"
SMOKE_URL="${SMOKE_URL:-http://localhost:3010}"

readonly TOKEN_ENDPOINT="${KC_URL}/realms/${KC_REALM}/protocol/openid-connect/token"

PASS=0
FAIL=0

red()    { printf '\033[31m%s\033[0m' "$*"; }
green()  { printf '\033[32m%s\033[0m' "$*"; }
yellow() { printf '\033[33m%s\033[0m' "$*"; }

# Fetches an access token via direct access grant. Echoes the raw token.
get_token() {
    local user="$1" pass="$2"
    curl -sS -X POST "$TOKEN_ENDPOINT" \
        -H 'Content-Type: application/x-www-form-urlencoded' \
        -d "grant_type=password" \
        -d "client_id=${KC_CLIENT}" \
        -d "username=${user}" \
        -d "password=${pass}" \
        -d "scope=openid" \
        | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p'
}

# Hits SMOKE_URL$path with the given method and (optional) bearer token,
# asserts the response status code matches $want.
assert_status() {
    local label="$1" method="$2" path="$3" want="$4" token="${5:-}"
    local args=(-sS -o /dev/null -w '%{http_code}' -X "$method" "${SMOKE_URL}${path}")
    if [[ -n "$token" ]]; then
        args+=(-H "Authorization: Bearer ${token}")
    fi
    local got
    got=$(curl "${args[@]}")
    if [[ "$got" == "$want" ]]; then
        printf '  %s %s %-4s %-15s → %s\n' "$(green PASS)" "$label" "$method" "$path" "$got"
        PASS=$((PASS + 1))
    else
        printf '  %s %s %-4s %-15s → got %s, want %s\n' "$(red FAIL)" "$label" "$method" "$path" "$got" "$want"
        FAIL=$((FAIL + 1))
    fi
}

header() {
    printf '\n%s %s\n' "$(yellow '##')" "$1"
}

# ---- Pre-flight ----------------------------------------------------------
header "Pre-flight"
if ! curl -sS -o /dev/null -w '%{http_code}\n' "${SMOKE_URL}/api/v1/health" | grep -q '^200$'; then
    printf '  %s smoke service not reachable at %s\n' "$(red ERR)" "$SMOKE_URL"
    exit 2
fi
if ! curl -sS -o /dev/null -w '%{http_code}\n' "${KC_URL}/realms/${KC_REALM}/.well-known/openid-configuration" | grep -q '^200$'; then
    printf '  %s Keycloak realm %s not reachable at %s\n' "$(red ERR)" "$KC_REALM" "$KC_URL"
    exit 2
fi
printf '  %s smoke service + Keycloak both up\n' "$(green OK)"

# ---- Public endpoint --------------------------------------------------
header "Public endpoint (no auth required)"
assert_status anon GET  /api/v1/health 200

# ---- Anonymous access to protected endpoints ----------------------------
header "Anonymous → 401 on protected endpoints"
assert_status anon GET  /api/v1/echo   401
assert_status anon POST /api/v1/echo   401

# ---- Bad token ----------------------------------------------------------
header "Bad token → 401"
assert_status bogus GET  /api/v1/echo  401 "not-a-real-jwt"
assert_status bogus POST /api/v1/echo  401 "not-a-real-jwt"

# ---- Active tenant (admin user) -----------------------------------------
header "admin@certifai.local (active) → full access"
TOKEN=$(get_token admin@certifai.local admin)
if [[ -z "$TOKEN" ]]; then
    printf '  %s failed to fetch token for admin\n' "$(red ERR)"
    exit 2
fi
assert_status active GET  /api/v1/echo 200 "$TOKEN"
assert_status active POST /api/v1/echo 200 "$TOKEN"

# ---- Active tenant (USER role) ------------------------------------------
header "user@certifai.local (active) → full access"
TOKEN=$(get_token user@certifai.local user)
assert_status active GET  /api/v1/echo 200 "$TOKEN"
assert_status active POST /api/v1/echo 200 "$TOKEN"

# ---- Trial tenant -------------------------------------------------------
header "trial@acme.local (trial) → full access"
TOKEN=$(get_token trial@acme.local trial)
assert_status trial  GET  /api/v1/echo 200 "$TOKEN"
assert_status trial  POST /api/v1/echo 200 "$TOKEN"

# ---- Frozen tenant ------------------------------------------------------
header "frozen@acme.local (frozen) → read-only, writes 402"
TOKEN=$(get_token frozen@acme.local frozen)
assert_status frozen GET  /api/v1/echo 200 "$TOKEN"
assert_status frozen POST /api/v1/echo 402 "$TOKEN"

# ---- Archived tenant ----------------------------------------------------
header "archived@acme.local (archived) → 410 everywhere"
TOKEN=$(get_token archived@acme.local archived)
assert_status archived GET  /api/v1/echo 410 "$TOKEN"
assert_status archived POST /api/v1/echo 410 "$TOKEN"

# ---- Summary ------------------------------------------------------------
printf '\n'
if [[ "$FAIL" -gt 0 ]]; then
    printf '%s %d passed, %d failed\n' "$(red FAIL)" "$PASS" "$FAIL"
    exit 1
fi
printf '%s %d/%d assertions passed\n' "$(green PASS)" "$PASS" "$PASS"
