;; identity/tests/introspect.sx — RFC 7662 §2.2 full introspection metadata
;; (sub, client_id, scope, exp, iat, token_type) alongside the live-lookup
;; active/inactive semantics.

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

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

(define idi-ev erlang-eval-ast)
(define idinm (fn (v) (get v :name)))

(identity-load-token!)

;; ── metadata fields ──────────────────────────────────────────────

(id-intr-test
  "introspect_full reports token_type bearer"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, web, read, 100),\n       case identity_tokens:introspect_full(R, T) of\n         {active, _, _, _, _, _, Tt} -> Tt;\n         {inactive} -> inactive\n       end"))
  "bearer")

(id-intr-test
  "introspect_full reports the subject"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, web, read, 100),\n       case identity_tokens:introspect_full(R, T) of\n         {active, Sub, _, _, _, _, _} -> Sub\n       end"))
  "alice")

(id-intr-test
  "introspect_full reports the client_id"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, mobile, read, 100),\n       case identity_tokens:introspect_full(R, T) of\n         {active, _, Cl, _, _, _, _} -> Cl\n       end"))
  "mobile")

(id-intr-test
  "introspect_full reports the scope"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, web, write, 100),\n       case identity_tokens:introspect_full(R, T) of\n         {active, _, _, Sc, _, _, _} -> Sc\n       end"))
  "write")

;; ── exp / iat reflect the logical clock ──────────────────────────

(id-intr-test
  "iat is the clock value at issue"
  (idi-ev
    "R = identity_tokens:start(),\n     identity_tokens:advance(R, 7),\n     {ok, T} = identity_tokens:issue(R, alice, web, read, 100),\n     case identity_tokens:introspect_full(R, T) of\n       {active, _, _, _, _, Iat, _} -> Iat\n     end")
  7)

(id-intr-test
  "exp is iat plus the ttl"
  (idi-ev
    "R = identity_tokens:start(),\n     identity_tokens:advance(R, 7),\n     {ok, T} = identity_tokens:issue(R, alice, web, read, 100),\n     case identity_tokens:introspect_full(R, T) of\n       {active, _, _, _, Exp, Iat, _} -> Exp - Iat\n     end")
  100)

;; ── inactive / expired / revoked ─────────────────────────────────

(id-intr-test
  "an expired token introspects inactive in full mode too"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, web, read, 100),\n       identity_tokens:advance(R, 100),\n       case identity_tokens:introspect_full(R, T) of\n         {active, _, _, _, _, _, _} -> active;\n         {inactive} -> inactive\n       end"))
  "inactive")

(id-intr-test
  "a revoked token introspects inactive in full mode"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       {ok, T} = identity_tokens:issue(R, alice, web, read),\n       identity_tokens:revoke(R, T),\n       case identity_tokens:introspect_full(R, T) of\n         {active, _, _, _, _, _, _} -> active;\n         {inactive} -> inactive\n       end"))
  "inactive")

(id-intr-test
  "an unknown token introspects inactive in full mode"
  (idinm
    (idi-ev
      "R = identity_tokens:start(),\n       Bogus = make_ref(),\n       case identity_tokens:introspect_full(R, Bogus) of\n         {active, _, _, _, _, _, _} -> active;\n         {inactive} -> inactive\n       end"))
  "inactive")

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