export type CheckoutRecord = {
  idempotencyKey: string
  orderId?: string
  clientSecret?: string
  mintCartVersion?: string | number
}

const keyFor = (cartId: string): string => `checkout:${cartId}`

function defaultMakeKey(): string {
  // Web-Crypto, host-agnostic. NO Math.random, NO Date.now-only keys.
  return crypto.randomUUID()
}

/** Read the persisted record for a cart, or null if absent/malformed. */
export function loadRecord(cartId: string): CheckoutRecord | null {
  try {
    const raw = sessionStorage.getItem(keyFor(cartId))
    if (raw === null) return null
    const parsed = JSON.parse(raw) as unknown
    if (typeof parsed !== 'object' || parsed === null) return null
    const r = parsed as Record<string, unknown>
    if (typeof r.idempotencyKey !== 'string') return null
    return {
      idempotencyKey: r.idempotencyKey,
      orderId: typeof r.orderId === 'string' ? r.orderId : undefined,
      clientSecret: typeof r.clientSecret === 'string' ? r.clientSecret : undefined,
      mintCartVersion:
        typeof r.mintCartVersion === 'string' || typeof r.mintCartVersion === 'number'
          ? r.mintCartVersion
          : undefined,
    }
  } catch {
    return null
  }
}

/** Write the full record (mint-once survival across the 3DS redirect). */
export function persistRecord(cartId: string, record: CheckoutRecord): void {
  try {
    sessionStorage.setItem(keyFor(cartId), JSON.stringify(record))
  } catch {
    // sessionStorage unavailable (SSR / disabled) — degrade to in-memory-only; the key
    // still mints, it just won't survive a redirect. Never throw on a storage write.
  }
}

/** Drop the record — terminal-success, reset(), or cart-content invalidation. */
export function clearRecord(cartId: string): void {
  try {
    sessionStorage.removeItem(keyFor(cartId))
  } catch {
    /* no-op */
  }
}

/**
 * Return the cart's existing key, or mint + persist a new one. Idempotent per cart:
 * repeated calls reuse the stored key (never regenerate per submit-click).
 */
export function ensureKey(cartId: string, makeKey: () => string = defaultMakeKey): string {
  const existing = loadRecord(cartId)
  if (existing) return existing.idempotencyKey
  const idempotencyKey = makeKey()
  persistRecord(cartId, { idempotencyKey })
  return idempotencyKey
}