;; identity/tests/facade.sx — the unified facade: one coordinator wiring
;; sessions+tokens, the audit ledger, and membership. Exercises the
;; cross-module integration (login/logout auditing, audit history, member
;; enrollment + projection) through the single `identity` door.

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

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

(define idfc-ev erlang-eval-ast)
(define idfcnm (fn (v) (get v :name)))

(identity-load-all!)

;; ── login + logout are audited through the ledger ────────────────

(id-facade-test
  "login then logout records login, issue, logout in order"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       {ok, Sid, _Tok} = identity:login(Svc, alice, web, read),\n       identity:logout(Svc, Sid),\n       case identity:history(Svc, alice) of\n         [login, issue, logout] -> ordered;\n         Other -> Other\n       end"))
  "ordered")

(id-facade-test
  "revoking a token is audited"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       {ok, _Sid, Tok} = identity:login(Svc, alice, web, read),\n       identity:revoke(Svc, Tok),\n       case identity:history(Svc, alice) of\n         [login, issue, revoke] -> ordered;\n         Other -> Other\n       end"))
  "ordered")

(id-facade-test
  "history is per-subject"
  (idfc-ev
    "Svc = identity:start(),\n     identity:login(Svc, alice, web, read),\n     identity:login(Svc, bob, cli, read),\n     identity:login(Svc, alice, mobile, read),\n     length(identity:history(Svc, alice))")
  4)

;; ── membership through the facade ────────────────────────────────

(id-facade-test
  "enroll makes the subject an active member"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       identity:enroll(Svc, alice, supporter),\n       case identity:member_status(Svc, alice) of\n         {ok, St, _} -> St;\n         {none} -> none\n       end"))
  "active")

(id-facade-test
  "enroll keeps the tier"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       identity:enroll(Svc, alice, supporter),\n       case identity:member_status(Svc, alice) of\n         {ok, _, Tier} -> Tier\n       end"))
  "supporter")

(id-facade-test
  "an enrolled member projects per-app"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       identity:enroll(Svc, alice, basic),\n       case identity:member_project(Svc, alice, market) of\n         {member, _, App} -> App;\n         {Tag, _} -> Tag\n       end"))
  "market")

(id-facade-test
  "a non-member projects as non_member"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       case identity:member_project(Svc, stranger, blog) of\n         {member, _, _} -> member;\n         {Tag, _} -> Tag\n       end"))
  "non_member")

;; ── the facade still proves identity ─────────────────────────────

(id-facade-test
  "verify still returns the subject after login"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       {ok, _Sid, Tok} = identity:login(Svc, alice, web, read),\n       case identity:verify(Svc, Tok) of\n         {active, Subject, _, _} -> Subject;\n         {inactive} -> inactive\n       end"))
  "alice")

;; ── identity and membership are distinct axes ────────────────────

(id-facade-test
  "logging in does not enroll membership"
  (idfcnm
    (idfc-ev
      "Svc = identity:start(),\n       identity:login(Svc, alice, web, read),\n       case identity:member_status(Svc, alice) of\n         {ok, St, _} -> St;\n         {none} -> none\n       end"))
  "none")

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