import { describe, expect, it } from 'vitest'
import {
  CartValidationError,
  MixedCurrencyError,
  isCartValidationError,
  isMixedCurrencyError,
} from './errors.js'

describe('commerce-cart error guards — structural, instanceof-free', () => {
  const cases = [
    {
      guard: isCartValidationError,
      error: new CartValidationError('qty', 'must be positive'),
      code: 'CART_VALIDATION',
      name: 'CartValidationError',
      crossRealm: { name: 'CartValidationError', code: 'CART_VALIDATION', field: 'qty' },
    },
    {
      guard: isMixedCurrencyError,
      error: new MixedCurrencyError('USD', 'EUR'),
      code: 'MIXED_CURRENCY',
      name: 'MixedCurrencyError',
      crossRealm: { name: 'MixedCurrencyError', code: 'MIXED_CURRENCY', expected: 'USD', got: 'EUR' },
    },
  ] as const

  for (const { guard, error, code, name, crossRealm } of cases) {
    it(`${name} guard accepts its own error and carries fields`, () => {
      expect(guard(error)).toBe(true)
      expect(error.code).toBe(code)
      if (error instanceof CartValidationError) {
        expect(error.field).toBe('qty')
        expect(error.detail).toBe('must be positive')
      }
      if (error instanceof MixedCurrencyError) {
        expect(error.expected).toBe('USD')
        expect(error.got).toBe('EUR')
      }
    })

    it(`${name} guard rejects plain object, different error, and wrong cross-realm shape`, () => {
      expect(guard({ field: 'qty' })).toBe(false)
      expect(guard(new Error('plain'))).toBe(false)
      expect(guard(null)).toBe(false)

      const other = cases.find((c) => c.name !== name)!
      expect(guard(other.error)).toBe(false)

      expect(guard({ name, code: 'WRONG_CODE' })).toBe(false)
      expect(guard({ name: 'OtherError', code })).toBe(false)
    })

    it(`${name} guard accepts cross-realm structural shape`, () => {
      expect(guard(crossRealm)).toBe(true)
    })
  }
})
