import { beforeEach, describe, expect, it } from 'vitest'
import {
  loadRecord,
  ensureKey,
  persistRecord,
  clearRecord,
  type CheckoutRecord,
} from './idempotency.js'

const CART = 'cart-1'
const KEY_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i

beforeEach(() => {
  sessionStorage.clear()
})

describe('idempotency-key lifecycle', () => {
  it('mints once and reuses the same key for the same cart', () => {
    const k1 = ensureKey(CART)
    const k2 = ensureKey(CART)
    expect(k1).toMatch(KEY_RE)
    expect(k2).toBe(k1) // reuse, never regenerate per call
  })

  it('honors an injected key generator', () => {
    let n = 0
    const make = () => `host-key-${n++}`
    expect(ensureKey(CART, make)).toBe('host-key-0')
    expect(ensureKey(CART, make)).toBe('host-key-0') // still reused
  })

  it('persists and reloads the full record across a simulated redirect', () => {
    const k = ensureKey(CART)
    persistRecord(CART, { idempotencyKey: k, orderId: 'o1', clientSecret: 'cs_1' })
    // simulate a fresh page after 3DS: module re-read from the same sessionStorage
    const r = loadRecord(CART) as CheckoutRecord
    expect(r.idempotencyKey).toBe(k)
    expect(r.orderId).toBe('o1')
    expect(r.clientSecret).toBe('cs_1')
  })

  it('clearRecord drops the record so the next ensureKey mints fresh', () => {
    const k1 = ensureKey(CART)
    clearRecord(CART)
    const k2 = ensureKey(CART)
    expect(k2).not.toBe(k1)
  })

  it('isolates records per cartId', () => {
    const a = ensureKey('cart-a')
    const b = ensureKey('cart-b')
    expect(a).not.toBe(b)
    expect((loadRecord('cart-a') as CheckoutRecord).idempotencyKey).toBe(a)
  })

  it('tolerates malformed stored JSON (returns null, mints fresh)', () => {
    sessionStorage.setItem('checkout:cart-x', '{not json')
    expect(loadRecord('cart-x')).toBeNull()
    expect(ensureKey('cart-x')).toMatch(KEY_RE)
  })
})