;; identity/tests/registry.sx — routing by id and by (subject, client),
;; SSO fan-out (one subject, many clients), and integration with live
;; session processes routed through the registry.

(define id-registry-test-count 0)
(define id-registry-test-pass 0)
(define id-registry-test-fails (list))

(define
  id-registry-test
  (fn
    (name actual expected)
    (set! id-registry-test-count (+ id-registry-test-count 1))
    (if
      (= actual expected)
      (set! id-registry-test-pass (+ id-registry-test-pass 1))
      (append! id-registry-test-fails {:name name :expected expected :actual actual}))))

(define idr-ev erlang-eval-ast)
(define idrnm (fn (v) (get v :name)))

(identity-load-session!)
(identity-load-registry!)

;; ── whereis by session id ────────────────────────────────────────

(id-registry-test
  "registered session is found by id"
  (idrnm
    (idr-ev
      "Me = self(),\n       Reg = identity_registry:start(),\n       identity_registry:register(Reg, s1, alice, web, Me),\n       case identity_registry:whereis_session(Reg, s1) of\n         {ok, _} -> found;\n         {error, _} -> missing\n       end"))
  "found")

(id-registry-test
  "unknown session id is not_found, not a crash"
  (idrnm
    (idr-ev
      "Reg = identity_registry:start(),\n       case identity_registry:whereis_session(Reg, nope) of\n         {ok, _} -> found;\n         {error, Why} -> Why\n       end"))
  "not_found")

;; ── lookup by (subject, client) — the SSO probe ──────────────────

(id-registry-test
  "lookup finds a session for subject+client"
  (idrnm
    (idr-ev
      "Me = self(),\n       Reg = identity_registry:start(),\n       identity_registry:register(Reg, s1, alice, web, Me),\n       case identity_registry:lookup(Reg, alice, web) of\n         {ok, _} -> found;\n         {error, _} -> missing\n       end"))
  "found")

(id-registry-test
  "lookup is precise: right subject, wrong client misses"
  (idrnm
    (idr-ev
      "Me = self(),\n       Reg = identity_registry:start(),\n       identity_registry:register(Reg, s1, alice, web, Me),\n       case identity_registry:lookup(Reg, alice, cli) of\n         {ok, _} -> found;\n         {error, _} -> missing\n       end"))
  "missing")

;; ── SSO fan-out: one subject, many clients ───────────────────────

(id-registry-test
  "sessions_for returns all of a subject's sessions"
  (idr-ev
    "Me = self(),\n     Reg = identity_registry:start(),\n     identity_registry:register(Reg, s1, alice, web, Me),\n     identity_registry:register(Reg, s2, alice, cli, Me),\n     identity_registry:register(Reg, s3, bob, web, Me),\n     case identity_registry:sessions_for(Reg, alice) of\n       {ok, L} -> length(L)\n     end")
  2)

(id-registry-test
  "sessions_for an unknown subject is empty"
  (idr-ev
    "Reg = identity_registry:start(),\n     case identity_registry:sessions_for(Reg, ghost) of\n       {ok, L} -> length(L)\n     end")
  0)

;; ── re-register replaces the row for that id (no duplicates) ──────

(id-registry-test
  "re-registering an id does not duplicate it"
  (idr-ev
    "Me = self(),\n     Reg = identity_registry:start(),\n     identity_registry:register(Reg, s1, alice, web, Me),\n     identity_registry:register(Reg, s1, alice, web, Me),\n     case identity_registry:sessions_for(Reg, alice) of\n       {ok, L} -> length(L)\n     end")
  1)

;; ── deregister removes routing ───────────────────────────────────

(id-registry-test
  "deregistered session is no longer found"
  (idrnm
    (idr-ev
      "Me = self(),\n       Reg = identity_registry:start(),\n       identity_registry:register(Reg, s1, alice, web, Me),\n       identity_registry:deregister(Reg, s1),\n       case identity_registry:whereis_session(Reg, s1) of\n         {ok, _} -> found;\n         {error, _} -> missing\n       end"))
  "missing")

;; ── integration: route to a live session and look it up ──────────

(id-registry-test
  "routed-to session answers lookup as active"
  (idrnm
    (idr-ev
      "Me = self(),\n       Reg = identity_registry:start(),\n       S = identity_session:start(s1, alice, web, Me, infinity),\n       identity_registry:register(Reg, s1, alice, web, S),\n       {ok, Pid} = identity_registry:lookup(Reg, alice, web),\n       case identity_session:lookup(Pid) of\n         {ok, {_,_,_,St}} -> St;\n         {error, St} -> St\n       end"))
  "active")

(define
  id-registry-test-summary
  (str "registry " id-registry-test-pass "/" id-registry-test-count))
