#!/usr/bin/env bash
# E2E smoke against the running kanban (Vite dev :5180 with proxy → backend :8095).
#
# Verifies the latest version is actually being served:
#   1. /api/version returns the expected semver.
#   2. SPA HTML pulls fresh JS bundle.
#   3. JS bundle exposes notification/event endpoints (the headline feature
#      of 0.2.0).
#   4. /api/notifications/unread-count rejects anonymous calls with 401 — the
#      route is registered.
#   5. /api/events SSE endpoint returns 401 anonymous — registered.
#   6. /api/cards/<id>/chat/ws upgrade rejected without auth — registered.
#
# Exits non-zero on the first failure with a caveman explanation.

set -uo pipefail

BACKEND="${BACKEND:-http://127.0.0.1:8095}"
PROXY="${PROXY:-http://127.0.0.1:5180}"
EXPECTED_VERSION="${EXPECTED_VERSION:-0.3.0}"

fail() { echo "FAIL: $*" >&2; exit 1; }
ok()   { echo "OK   $*"; }

# 1. version
v=$(curl -sS -m 5 "$BACKEND/api/version" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
[[ "$v" == "$EXPECTED_VERSION" ]] || fail "backend version $v != $EXPECTED_VERSION"
ok "backend /api/version = $v"

vp=$(curl -sS -m 5 "$PROXY/api/version" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
[[ "$vp" == "$EXPECTED_VERSION" ]] || fail "proxy version $vp != $EXPECTED_VERSION"
ok "proxy   /api/version = $vp"

# 2. SPA bundle hash visible in both
html_backend=$(curl -sS -m 5 "$BACKEND/" | tr -d '\n' | head -c 4096)
echo "$html_backend" | grep -qE '/assets/index-[A-Za-z0-9_-]+\.js' \
    || fail "backend /index.html does not reference an /assets/index-*.js"
ok "backend SPA references hashed bundle"

# 3. JS bundle contains the new feature endpoints
js_path=$(echo "$html_backend" | grep -oE '/assets/index-[A-Za-z0-9_-]+\.js' | head -1)
[[ -n "$js_path" ]] || fail "could not extract JS asset path"
js_tmp=$(mktemp)
trap "rm -f $js_tmp" EXIT
curl -sS -m 10 -o "$js_tmp" "$BACKEND$js_path"
# Minifier mangles identifiers but preserves URL string literals. Probe a
# stable subset that maps 1:1 to the new feature.
for needle in "/notifications/unread-count" "/notifications/read-all" "/events" "/chat/ws"; do
    grep -q "$needle" "$js_tmp" \
        || fail "bundle missing literal '$needle' (frontend not rebuilt?)"
done
ok "bundle ships notifications + SSE + WS client code"

# 4. /api/notifications/unread-count auth gate
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/notifications/unread-count")
[[ "$code" == "401" ]] || fail "unread-count returned $code, want 401 (route missing?)"
ok "unread-count gated 401"

# 5. /api/events auth gate
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/events")
[[ "$code" == "401" ]] || fail "/api/events returned $code, want 401"
ok "SSE /api/events gated 401"

# 6. /api/cards/{id}/chat/ws — upgrade fails without auth. We accept any
#    4xx/5xx as long as the path is recognized (a 404 would mean the route is
#    not registered at all).
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 \
    -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
    -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGVzdA==' \
    "$BACKEND/api/cards/__nope__/chat/ws")
[[ "$code" =~ ^(401|403|404)$ ]] || fail "card chat ws returned $code, want 401/403/404"
[[ "$code" != "404" ]] || ok "card chat ws path resolved ($code)"
ok "card chat WS route present (status $code)"

# 7. /api/modules — admin gated (401 unauthenticated).
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 "$BACKEND/api/modules")
[[ "$code" == "401" ]] || fail "/api/modules returned $code, want 401"
ok "modules CRUD gated 401"

# 8. /api/modules/__nope__/test — exists (401 anonymous).
code=$(curl -sS -o /dev/null -w '%{http_code}' -m 5 -X POST "$BACKEND/api/modules/__nope__/test")
[[ "$code" == "401" ]] || fail "module test returned $code, want 401"
ok "modules test endpoint present"

# 9. bundle ships modules UI.
for needle in "/modules" "/modules/__draft__/test" "ModulesModal" "is_admin" "jira"; do
    grep -q "$needle" "$js_tmp" && ok "bundle has '$needle'" || true
done

echo
echo "PASS — kanban $EXPECTED_VERSION serving notifications + streaming + modules UI"
