/**
 * Typed failure modes of the OIDC callback. The controller maps each
 * to a query-param identifier on the SPA redirect so the front-end
 * can render an appropriate message without inventing strings.
 *
 * Keep this list flat — the controller's `switch` is exhaustive
 * thanks to TypeScript's narrowing on `kind`.
 */
export type AuthCodeFlowError =
  | { kind: 'state-mismatch' }
  | { kind: 'flow-expired' }
  | { kind: 'token-exchange-failed'; cause: string };

export class AuthCodeFlowException extends Error {
  constructor(readonly failure: AuthCodeFlowError) {
    super(`auth code flow failed: ${failure.kind}`);
    this.name = 'AuthCodeFlowException';
  }
}

/**
 * Stable short codes used as `?auth_error=<code>` on the SPA-bound
 * redirect. Same identifiers as the discriminant `kind` so log
 * grepping correlates trivially.
 */
export function authErrorCode(failure: AuthCodeFlowError): string {
  return failure.kind;
}
