#!/usr/bin/env bash
# m13b_w1_smoke.sh — End-to-end smoke for the M13b W1 tenant CRUD.
#
# Walks through:
#   1. authd /health and /metrics
#   2. login (super_admin) → access + refresh
#   3. GET /v1/tenants (initially empty or has prior smoke data)
#   4. POST /v1/tenants (create) — super_admin OK
#   5. GET /v1/tenants/{id} (the one we just created)
#   6. PATCH /v1/tenants/{id} (change display_name + rate_limit_per_sec)
#   7. POST /v1/tenants/{id}/status (suspend)
#   8. POST /v1/tenants/{id}/status (activate)
#   9. POST /v1/tenants (duplicate slug) → 409
#   10. POST /v1/tenants (bad slug) → 400
#   11. Login as tenant_admin of the new tenant → can GET own
#   12. tenant_admin trying to GET another tenant's id → 403
#   13. tenant_admin trying to POST /v1/tenants → 403
#   14. POST /v1/tenants/{id}/status as tenant_admin → 403
#   15. POST /v1/tenants/{id}/status with bad status → 400
#   16. (cleanup) super_admin archives the new tenant
#
# Requires:
#   - authd running on $BA_AUTHD_HTTP (default http://127.0.0.1:8804)
#   - $BA_AUTHD_JWT_SECRET set
#   - super_admin user in Postgres (scripts/bootstrap-super-admin.sh)
#
# Run:
#   bash scripts/m13b_w1_smoke.sh
#
# Exits 0 if all steps pass.

set -euo pipefail
cd "$(dirname "$0")/.."

AUTHD="${BA_AUTHD_HTTP:-http://127.0.0.1:8804}"
SUPER_EMAIL="${BA_SMOKE_SUPER_EMAIL:-super@broad-announce.test}"
SUPER_PASSWORD="${BA_SMOKE_SUPER_PASSWORD:-test-password-123}"

# We need a tenant_admin in the new tenant for steps 11-14. The
# simplest path: after creating the tenant, invite one via
# /v1/users/invite (super_admin), grab the magic token from the
# DB, and use it to set the password. This is exactly the flow
# that scripts/m13a_smoke.sh avoids (because it just checks the
# route is wired), but here we need a real user. v1.1 should
# expose a /v1/users/bootstrap-tenant-admin endpoint to make this
# easier; for now we go through the SQL path.
DSN="${BA_POSTGRES_DSN:-${PG_DSN:-postgres://ba:ba@localhost:5432/ba?sslmode=disable}}"

PASS=0
FAIL=0
RESULTS=()
TENANT_SLUG="smoke-$(date +%s)"
TENANT_EMAIL="ops-${TENANT_SLUG}@smoke.test"
TENANT_ADMIN_EMAIL="admin-${TENANT_SLUG}@smoke.test"
TENANT_ADMIN_PASSWORD="smoke-test-password-1234"

check() {
  local name="$1"
  local actual="$2"
  local want="$3"
  if [[ "$actual" == "$want" ]]; then
    PASS=$((PASS+1))
    RESULTS+=("OK   $name")
  else
    FAIL=$((FAIL+1))
    RESULTS+=("FAIL $name (got $actual, want $want)")
  fi
}

# JSON helper: jq-less extract of a top-level string field.
# Usage: json_field body field
json_field() {
  echo "$1" | python3 -c "import json,sys; d=json.load(sys.stdin); k='$2'.split('.'); v=d
for kk in k:
  v=v[kk] if isinstance(v,dict) else v[int(kk)]
print(v if not isinstance(v,(list,dict,bool)) else json.dumps(v))"
}

# -------------------------------------------------------------------
# 1. health
# -------------------------------------------------------------------
status=$(curl -s -o /dev/null -w "%{http_code}" "$AUTHD/health")
check "1. authd /health" "$status" "200"

# -------------------------------------------------------------------
# 2. login (super_admin)
# -------------------------------------------------------------------
login_body=$(curl -s -X POST "$AUTHD/v1/auth/login" \
  -H 'Content-Type: application/json' \
  -d "{\"email\":\"$SUPER_EMAIL\",\"password\":\"$SUPER_PASSWORD\"}")
SUPER_TOKEN=$(json_field "$login_body" access_token)
if [[ -z "$SUPER_TOKEN" ]]; then
  echo "FATAL: super_admin login failed: $login_body"
  exit 1
fi
check "2. super_admin login" "200" "200"

# -------------------------------------------------------------------
# 3. GET /v1/tenants (initial list)
# -------------------------------------------------------------------
list=$(curl -s -H "Authorization: Bearer $SUPER_TOKEN" "$AUTHD/v1/tenants?limit=10")
total=$(json_field "$list" total)
echo "    initial tenant count: $total"
check "3. GET /v1/tenants" "200" "200"

# -------------------------------------------------------------------
# 4. POST /v1/tenants (create)
# -------------------------------------------------------------------
create=$(curl -s -w "\n%{http_code}" -X POST "$AUTHD/v1/tenants" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d "{\"slug\":\"$TENANT_SLUG\",\"display_name\":\"Smoke Tenant\",\"contact_email\":\"$TENANT_EMAIL\",\"rate_limit_per_sec\":5000,\"fcm_shared\":true}")
create_code=$(echo "$create" | tail -1)
create_body=$(echo "$create" | head -n -1)
TENANT_ID=$(json_field "$create_body" id)
check "4. POST /v1/tenants" "$create_code" "201"
[[ -n "$TENANT_ID" ]] || { echo "FATAL: no tenant id"; exit 1; }
echo "    new tenant: $TENANT_ID"

# -------------------------------------------------------------------
# 5. GET /v1/tenants/{id}
# -------------------------------------------------------------------
get=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $SUPER_TOKEN" "$AUTHD/v1/tenants/$TENANT_ID")
check "5. GET /v1/tenants/{id}" "$get" "200"

# -------------------------------------------------------------------
# 6. PATCH /v1/tenants/{id}
# -------------------------------------------------------------------
patch=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH "$AUTHD/v1/tenants/$TENANT_ID" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"display_name":"Smoke Tenant (edited)","rate_limit_per_sec":7500}')
check "6. PATCH /v1/tenants/{id}" "$patch" "200"

# -------------------------------------------------------------------
# 7. POST /v1/tenants/{id}/status suspend
# -------------------------------------------------------------------
sus=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants/$TENANT_ID/status" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status":"suspended"}')
check "7. POST /v1/tenants/{id}/status suspend" "$sus" "200"

# -------------------------------------------------------------------
# 8. POST /v1/tenants/{id}/status activate
# -------------------------------------------------------------------
act=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants/$TENANT_ID/status" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status":"active"}')
check "8. POST /v1/tenants/{id}/status activate" "$act" "200"

# -------------------------------------------------------------------
# 9. POST /v1/tenants (duplicate slug) → 409
# -------------------------------------------------------------------
dup=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d "{\"slug\":\"$TENANT_SLUG\",\"display_name\":\"Dup\",\"contact_email\":\"$TENANT_EMAIL\"}")
check "9. POST /v1/tenants (dup slug)" "$dup" "409"

# -------------------------------------------------------------------
# 10. POST /v1/tenants (bad slug) → 400
# -------------------------------------------------------------------
bad=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"slug":"Bad Slug!","display_name":"x","contact_email":"a@b.c"}')
check "10. POST /v1/tenants (bad slug)" "$bad" "400"

# -------------------------------------------------------------------
# 11. Bootstrap a tenant_admin in the new tenant.
#     This goes through the SQL path because we don't have an
#     open invite-magic endpoint in v1.
# -------------------------------------------------------------------
export PGPASSWORD="$(echo "$DSN" | sed -E 's|.*://[^:]+:([^@]+)@.*|\1|')"
HASH=$(python3 -c "
import bcrypt
print(bcrypt.hashpw(b'${TENANT_ADMIN_PASSWORD}', bcrypt.gensalt(rounds=10)).decode())
")
psql "$DSN" -v ON_ERROR_STOP=0 -X -q -c "
INSERT INTO auth.users (tenant_id, email, role, status, password_hash)
SELECT id, '${TENANT_ADMIN_EMAIL}', 'tenant_admin', 'active', '${HASH}'
FROM auth.tenants WHERE slug = '${TENANT_SLUG}'
ON CONFLICT (email, tenant_id) WHERE tenant_id IS NOT NULL DO UPDATE SET password_hash = EXCLUDED.password_hash, status = 'active';
" >/dev/null
ta_login=$(curl -s -X POST "$AUTHD/v1/auth/login" \
  -H 'Content-Type: application/json' \
  -d "{\"email\":\"$TENANT_ADMIN_EMAIL\",\"password\":\"$TENANT_ADMIN_PASSWORD\"}")
TA_TOKEN=$(json_field "$ta_login" access_token)
if [[ -z "$TA_TOKEN" ]]; then
  echo "FATAL: tenant_admin login failed: $ta_login"
  exit 1
fi
check "11. tenant_admin login (own tenant)" "200" "200"

# 11b. tenant_admin can GET own tenant
ta_get=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TA_TOKEN" "$AUTHD/v1/tenants/$TENANT_ID")
check "11b. tenant_admin GET own tenant" "$ta_get" "200"

# 11c. tenant_admin can PATCH own display_name (restricted fields)
ta_patch=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH "$AUTHD/v1/tenants/$TENANT_ID" \
  -H "Authorization: Bearer $TA_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"display_name":"Smoke (tenant-admin edited)"}')
check "11c. tenant_admin PATCH own display_name" "$ta_patch" "200"

# 11d. tenant_admin CANNOT change rate_limit_per_sec (restricted)
ta_rl=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH "$AUTHD/v1/tenants/$TENANT_ID" \
  -H "Authorization: Bearer $TA_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"rate_limit_per_sec":1234}')
check "11d. tenant_admin PATCH own rate_limit_per_sec (forbidden)" "$ta_rl" "400"

# -------------------------------------------------------------------
# 12. tenant_admin trying to GET another tenant's id → 403
#     (use a random uuid that won't exist; canAccessTenant fails
#      before the DB lookup, so we get 403 not 404)
# -------------------------------------------------------------------
fake_id="00000000-0000-0000-0000-000000000000"
ta_other=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TA_TOKEN" "$AUTHD/v1/tenants/$fake_id")
check "12. tenant_admin GET other tenant" "$ta_other" "403"

# -------------------------------------------------------------------
# 13. tenant_admin trying to POST /v1/tenants → 403
# -------------------------------------------------------------------
ta_create=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants" \
  -H "Authorization: Bearer $TA_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"slug":"x","display_name":"x","contact_email":"a@b.c"}')
check "13. tenant_admin POST /v1/tenants" "$ta_create" "403"

# -------------------------------------------------------------------
# 14. tenant_admin trying to POST /v1/tenants/{id}/status → 403
# -------------------------------------------------------------------
ta_st=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants/$TENANT_ID/status" \
  -H "Authorization: Bearer $TA_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status":"suspended"}')
check "14. tenant_admin POST status" "$ta_st" "403"

# -------------------------------------------------------------------
# 15. POST /v1/tenants/{id}/status with bad status → 400
# -------------------------------------------------------------------
bad_st=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants/$TENANT_ID/status" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status":"paused"}')
check "15. POST status (bad value)" "$bad_st" "400"

# -------------------------------------------------------------------
# 16. cleanup: super_admin archives the new tenant
# -------------------------------------------------------------------
arc=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$AUTHD/v1/tenants/$TENANT_ID/status" \
  -H "Authorization: Bearer $SUPER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status":"archived"}')
check "16. POST status archived (cleanup)" "$arc" "200"

# -------------------------------------------------------------------
# summary
# -------------------------------------------------------------------
echo
echo "=== M13b W1 smoke results ==="
printf '%s\n' "${RESULTS[@]}"
echo
echo "Passed: $PASS   Failed: $FAIL"
[[ $FAIL -eq 0 ]] || exit 1
