// Pure OIDC-login state helpers (no imports) so they're unit-testable under the
// tsx + node:test harness. The SDK-driven flow lives in oidcLoginUtil.ts.

/**
 * Dynamic-registration cache. MAS issues a `client_id` per dynamic registration;
 * caching by issuer (scoped to the current redirectUri) avoids re-registering on
 * every login. Invalidated when the redirectUri changes or the provider later
 * rejects the cached id (`invalid_client`).
 */
const REG_CACHE_KEY = 'cinny_oidc_dynamic_clients';
type RegEntry = { clientId: string; redirectUri: string };
type RegCache = Record<string, RegEntry>;

const readRegCache = (): RegCache => {
  try {
    const raw = localStorage.getItem(REG_CACHE_KEY);
    return raw ? (JSON.parse(raw) as RegCache) : {};
  } catch {
    return {};
  }
};
const writeRegCache = (cache: RegCache): void => {
  localStorage.setItem(REG_CACHE_KEY, JSON.stringify(cache));
};

export const getCachedClientId = (issuer: string, redirectUri: string): string | undefined => {
  const entry = readRegCache()[issuer];
  return entry && entry.redirectUri === redirectUri ? entry.clientId : undefined;
};
export const cacheClientId = (issuer: string, clientId: string, redirectUri: string): void => {
  const cache = readRegCache();
  cache[issuer] = { clientId, redirectUri };
  writeRegCache(cache);
};
export const invalidateCachedClient = (issuer: string): void => {
  const cache = readRegCache();
  if (cache[issuer]) {
    delete cache[issuer];
    writeRegCache(cache);
  }
};

/** Parsed shape of the provider's redirect back to our callback URL. */
export type OidcCallbackParams =
  | { kind: 'success'; code: string; state: string }
  | { kind: 'error'; error: string; errorDescription?: string }
  | { kind: 'invalid' };

/** Pure: classify the callback query string into success / error / invalid. */
export const parseOidcCallbackParams = (search: string): OidcCallbackParams => {
  const params = new URLSearchParams(search);
  const error = params.get('error');
  if (error) {
    return { kind: 'error', error, errorDescription: params.get('error_description') ?? undefined };
  }
  const code = params.get('code');
  const state = params.get('state');
  if (code && state) return { kind: 'success', code, state };
  return { kind: 'invalid' };
};
