#!/usr/bin/env bash
#
# CareMeet end-to-end smoke test — API layer.
#
# Exercises the real chain a hospital integration depends on:
#   platform login -> onboard tenant -> activate -> HMAC-signed room creation
#   -> join token issued -> JWT verifies against the public key
#
# Run after any change to auth, tenancy or token issuance. It catches the
# class of break that unit tests miss: the seams between them.
#
#   ./tools/smoke_test.sh
#
set -uo pipefail

API=${API:-http://127.0.0.1:8080}
JAR=$(mktemp)
PASS=0; FAIL=0

ok()   { echo "  PASS  $1"; PASS=$((PASS+1)); }
bad()  { echo "  FAIL  $1"; echo "        $2" | head -3; FAIL=$((FAIL+1)); }
step() { echo; echo "== $1"; }

json() { python3 -c "import sys,json;d=json.load(sys.stdin);print(json.dumps(d.get('$1','') if '$1' else d))" 2>/dev/null; }

step "1. Health"
R=$(curl -sS "$API/v1/health")
echo "$R" | grep -q '"ok":true' && ok "API responding" || bad "API health" "$R"

step "2. Platform admin login"
R=$(curl -sS -c "$JAR" -X POST "$API/v1/auth/platform/login" \
     -H 'Content-Type: application/json' \
     -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASS\"}")
echo "$R" | grep -q '"ok":true' && ok "signed in" || bad "platform login" "$R"

step "3. Rejects a wrong password"
R=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$API/v1/auth/platform/login" \
     -H 'Content-Type: application/json' \
     -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"definitely-wrong\"}")
[ "$R" = "401" ] && ok "bad password rejected (401)" || bad "expected 401" "got $R"

step "4. Onboard a tenant"
SUB="smoke$RANDOM"
R=$(curl -sS -b "$JAR" -X POST "$API/v1/tenants" -H 'Content-Type: application/json' -d "{
  \"name\":\"Smoke Test Hospital\",\"subdomain\":\"$SUB\",\"plan_code\":\"hospital\",
  \"city\":\"Mumbai\",\"admin_name\":\"Test Admin\",\"admin_email\":\"admin@$SUB.test\",
  \"products\":[\"myopd\"]}")
TENANT_ID=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin)['tenant']['tenant_id'])" 2>/dev/null)
API_KEY=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin)['tenant']['api_clients'][0]['api_key'])" 2>/dev/null)
API_SECRET=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin)['tenant']['api_clients'][0]['api_secret'])" 2>/dev/null)
[ -n "${TENANT_ID:-}" ] && ok "tenant created (id $TENANT_ID)" || bad "tenant creation" "$R"
[ -n "${API_SECRET:-}" ] && ok "API credentials returned once" || bad "no API credentials" "$R"

step "5. Duplicate subdomain is refused"
R=$(curl -sS -o /dev/null -w '%{http_code}' -b "$JAR" -X POST "$API/v1/tenants" \
     -H 'Content-Type: application/json' -d "{
     \"name\":\"Dup\",\"subdomain\":\"$SUB\",\"plan_code\":\"hospital\",
     \"admin_name\":\"A\",\"admin_email\":\"a@dup.test\"}")
[ "$R" = "409" ] && ok "duplicate subdomain rejected (409)" || bad "expected 409" "got $R"

step "6. Activate the tenant"
R=$(curl -sS -b "$JAR" -X PUT "$API/v1/tenants/$TENANT_ID/status" \
     -H 'Content-Type: application/json' -d '{"status":"active"}')
echo "$R" | grep -q '"ok":true' && ok "tenant active" || bad "activation" "$R"

step "7. Room creation rejects an unsigned request"
R=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$API/v1/rooms" \
     -H 'Content-Type: application/json' -d '{"participants":[]}')
[ "$R" = "401" ] && ok "unsigned request rejected (401)" || bad "expected 401" "got $R"

step "8. Room creation rejects a bad signature"
TS=$(date +%s)
R=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$API/v1/rooms" \
     -H 'Content-Type: application/json' -H "X-API-Key: $API_KEY" \
     -H "X-API-Secret: $API_SECRET" -H "X-Timestamp: $TS" \
     -H "X-Signature: 0000000000000000000000000000000000000000000000000000000000000000" \
     -d '{"participants":[{"call_role":"doctor","display_name":"D"}]}')
[ "$R" = "401" ] && ok "bad signature rejected (401)" || bad "expected 401" "got $R"

step "9. Room creation rejects a replayed timestamp"
BODY='{"participants":[{"call_role":"doctor","display_name":"D"}]}'
OLD=$(( $(date +%s) - 4000 ))
SIG=$(printf '%s\n%s' "$OLD" "$BODY" | openssl dgst -sha256 -hmac "$API_SECRET" -r | cut -d' ' -f1)
R=$(curl -sS -o /dev/null -w '%{http_code}' -X POST "$API/v1/rooms" \
     -H 'Content-Type: application/json' -H "X-API-Key: $API_KEY" \
     -H "X-API-Secret: $API_SECRET" -H "X-Timestamp: $OLD" -H "X-Signature: $SIG" -d "$BODY")
[ "$R" = "401" ] && ok "stale timestamp rejected (401)" || bad "expected 401" "got $R"

step "10. Create a consultation (correctly signed)"
BODY='{"purpose":"opd_consult","external_ref":"SMOKE-001","max_participants":2,"recording_mode":"off","participants":[{"call_role":"doctor","display_name":"Dr Test"},{"call_role":"patient","display_name":"Test Patient","phone":"+919820000000"}]}'
TS=$(date +%s)
SIG=$(printf '%s\n%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_SECRET" -r | cut -d' ' -f1)
R=$(curl -sS -X POST "$API/v1/rooms" -H 'Content-Type: application/json' \
     -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" \
     -H "X-Timestamp: $TS" -H "X-Signature: $SIG" -d "$BODY")
ROOM=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin)['room']['room_uuid'])" 2>/dev/null)
TOKEN=$(echo "$R" | python3 -c "import sys,json;print(json.load(sys.stdin)['participants'][0]['token'])" 2>/dev/null)
[ -n "${ROOM:-}" ] && ok "consultation created ($ROOM)" || bad "room creation" "$R"
[ -n "${TOKEN:-}" ] && ok "join tokens issued" || bad "no join token" "$R"

step "11. Join token verifies against the public key"
if [ -n "${TOKEN:-}" ]; then
  V=$(php -r '
    $t = $argv[1]; $pub = file_get_contents($argv[2]);
    [$h,$p,$s] = explode(".", $t);
    $d = fn($x) => base64_decode(strtr($x, "-_", "+/"));
    $okSig = openssl_verify("$h.$p", $d($s), $pub, OPENSSL_ALGO_SHA256) === 1;
    $claims = json_decode($d($p), true);
    $need = ["jti","tid","room","pid","role","perm","iss","aud","exp"];
    $missing = array_diff($need, array_keys($claims));
    echo $okSig ? "SIG_OK " : "SIG_BAD ";
    echo $missing ? "MISSING:".implode(",",$missing) : "CLAIMS_OK";
    echo " role=".$claims["role"]." perms=".count($claims["perm"]);
    echo " ttl=".($claims["exp"] - time())."s";
  ' "$TOKEN" "$JWT_PUB")
  case "$V" in
    SIG_OK*CLAIMS_OK*) ok "RS256 signature and claims valid — $V" ;;
    *) bad "token verification" "$V" ;;
  esac
fi

step "12. Plan limits are enforced"
BODY='{"participants":[{"call_role":"doctor","display_name":"D"}],"max_participants":20}'
TS=$(date +%s)
SIG=$(printf '%s\n%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_SECRET" -r | cut -d' ' -f1)
R=$(curl -sS -X POST "$API/v1/rooms" -H 'Content-Type: application/json' \
     -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" \
     -H "X-Timestamp: $TS" -H "X-Signature: $SIG" -d "$BODY")
echo "$R" | grep -q 'plan_restriction' && ok "over-plan participant count refused" || bad "plan limit not enforced" "$R"

step "13. Token refresh mints a fresh credential"
PID=$(mariadb -N -B caremeet -e "SELECT id FROM room_participants WHERE room_id=(SELECT id FROM rooms WHERE room_uuid='$ROOM') LIMIT 1" 2>/dev/null)
if [ -n "${PID:-}" ]; then
  R=$(curl -sS -X POST "$API/v1/participants/$PID/token")
  echo "$R" | grep -q '"token"' && ok "fresh token issued at click time" || bad "token refresh" "$R"
fi

step "14. Cross-tenant access is blocked"
R=$(curl -sS -o /dev/null -w '%{http_code}' "$API/v1/rooms/00000000-0000-0000-0000-000000000000")
[ "$R" = "404" ] || [ "$R" = "401" ] && ok "unknown room not disclosed ($R)" || bad "expected 404/401" "got $R"

echo
echo "=========================================="
echo "  passed: $PASS   failed: $FAIL"
echo "=========================================="
rm -f "$JAR"
[ "$FAIL" -eq 0 ]
