import { describe, expect, it } from 'vitest'
import {
  UnsupportedOperation,
  getAdapter,
  registerMarketingAdapter,
  requireCapability,
  type MarketingAdapter,
  type MarketingSupports,
} from './index.js'

function fakeAdapter(supports: MarketingSupports): MarketingAdapter {
  return {
    name: 'fake',
    supports,
    async upsertContact() {},
    async removeContact() {},
    async tagContact() {},
    async createList() {
      return { id: 'l1', name: 'List' }
    },
    async lists() {
      return []
    },
    async createCampaign(input) {
      return { ...input, id: 'c1' }
    },
    async sendCampaign() {
      return { sent: [], refused: [] }
    },
    async campaignStats() {
      return { opens: 0, clicks: 0, bounces: 0, unsubs: 0 }
    },
    async syncSuppression() {
      return []
    },
  }
}

describe('requireCapability', () => {
  it('throws UnsupportedOperation when the capability flag is false', () => {
    const adapter = fakeAdapter({ segments: false, scheduling: true, automation: false })
    expect(() => requireCapability(adapter, 'segments')).toThrow(UnsupportedOperation)
    expect(() => requireCapability(adapter, 'segments')).toThrow(/segments/)
  })
})

describe('getAdapter', () => {
  it('throws when no factory is registered for the adapter name', () => {
    expect(() => getAdapter('missing', {})).toThrow(/No marketing adapter factory/)
  })

  it('returns an adapter from a registered factory', () => {
    const adapter = fakeAdapter({ segments: true, scheduling: false, automation: false })
    registerMarketingAdapter('self-managed', () => adapter)
    expect(getAdapter('self-managed', {})).toBe(adapter)
  })
})

describe('UnsupportedOperation', () => {
  it('names the unsupported capability', () => {
    const err = new UnsupportedOperation('automation')
    expect(err.name).toBe('UnsupportedOperation')
    expect(err.capability).toBe('automation')
  })
})
