import { describe, expect, it } from 'vitest'
import {
  ComplianceError,
  assertRecipientEligible,
  confirmDoubleOptIn,
  createMemoryComplianceStore,
  executeCompliantSend,
  getAdapter,
  type Campaign,
  type CampaignLegalContext,
  type CompliantRecipientMessage,
  type CompliantSendInput,
} from '@platform-modules/marketing'

const legal: CampaignLegalContext = {
  region: 'US',
  legal: {
    spf: true,
    dkim: true,
    dmarc: true,
    physicalPostalAddress: '123 Main St, Springfield',
    advertisingLabel: 'Advertisement',
  },
  oneClickUnsubscribeUrl: 'https://example.com/u/abc',
}

const campaign: Campaign = {
  id: 'c1',
  name: 'Newsletter',
  subject: 'Hello',
  html: '<html><body>Hi <a href="https://example.com/deal">deal</a></body></html>',
  listIds: ['l1'],
}

function input(over: Partial<CompliantSendInput> = {}): CompliantSendInput {
  return {
    campaignId: 'c1',
    campaign,
    legal,
    recipients: [],
    trackingBaseUrl: 'https://track.example.com',
    ...over,
  }
}

function capture() {
  const messages: CompliantRecipientMessage[] = []
  return { messages, sendOne: async (m: CompliantRecipientMessage) => void messages.push(m) }
}

describe('marketing consumer fixture (Gate 3 — compliance seam)', () => {
  it('blocks the whole send when the sender legal declaration is incomplete', async () => {
    const store = createMemoryComplianceStore()
    const { sendOne, messages } = capture()
    const badAuth = { ...legal, legal: { ...legal.legal, dkim: false } }

    await expect(
      executeCompliantSend(store, input({ legal: badAuth, recipients: ['a@example.com'] }), sendOne),
    ).rejects.toMatchObject({ code: 'missing-domain-auth' })
    await expect(
      executeCompliantSend(store, input({ legal: badAuth }), sendOne),
    ).rejects.toBeInstanceOf(ComplianceError)
    expect(messages).toHaveLength(0) // fail-closed: nothing leaves before the gate passes
  })

  it('refuses suppressed + unconfirmed recipients and sends only the eligible (EU opt-in)', async () => {
    const store = createMemoryComplianceStore({
      suppressed: [{ email: 'sup@example.com', reason: 'unsubscribe', suppressedAt: '2026-01-01' }],
      consents: [{ email: 'ok@example.com', doubleOptInConfirmed: true, trackingConsent: false }],
    })
    const { sendOne, messages } = capture()

    const result = await executeCompliantSend(
      store,
      input({
        legal: { ...legal, region: 'EU' },
        recipients: ['sup@example.com', 'ok@example.com', 'new@example.com'],
      }),
      sendOne,
    )

    expect(result.sent).toEqual(['ok@example.com'])
    expect(result.refused.map((r) => r.code).sort()).toEqual(['suppressed', 'unconfirmed-consent'])
    expect(messages.map((m) => m.email)).toEqual(['ok@example.com'])
  })

  it('injects RFC 8058 one-click unsubscribe headers on every compliant send', async () => {
    const store = createMemoryComplianceStore({
      consents: [{ email: 'ok@example.com', doubleOptInConfirmed: true, trackingConsent: false }],
    })
    const { sendOne, messages } = capture()

    await executeCompliantSend(store, input({ recipients: ['ok@example.com'] }), sendOne)

    expect(messages[0]?.headers['List-Unsubscribe']).toBe('<https://example.com/u/abc>')
    expect(messages[0]?.headers['List-Unsubscribe-Post']).toBe('List-Unsubscribe=One-Click')
  })

  it('keeps tracking off by default and enables it only with recorded per-contact consent', async () => {
    const store = createMemoryComplianceStore({
      consents: [
        { email: 'track@example.com', doubleOptInConfirmed: true, trackingConsent: true },
        { email: 'notrack@example.com', doubleOptInConfirmed: true, trackingConsent: false },
      ],
    })
    const { sendOne, messages } = capture()

    await executeCompliantSend(
      store,
      input({ recipients: ['track@example.com', 'notrack@example.com'] }),
      sendOne,
    )

    const tracked = messages.find((m) => m.email === 'track@example.com')!
    const untracked = messages.find((m) => m.email === 'notrack@example.com')!
    expect(tracked.html).toContain('/o/c1/') // open pixel
    expect(tracked.html).toContain('/c/c1/') // click redirect
    expect(untracked.html).not.toContain('/o/')
    expect(untracked.html).toContain('href="https://example.com/deal"') // original href preserved
  })

  it('gates double opt-in by region (US implicit, EU requires confirmation)', () => {
    expect(assertRecipientEligible('a@example.com', null, false, 'US')).toBeNull()
    expect(assertRecipientEligible('a@example.com', null, false, 'EU')?.code).toBe('unconfirmed-consent')
    expect(assertRecipientEligible('a@example.com', null, true, 'US')?.code).toBe('suppressed')
  })

  it('confirmDoubleOptIn records normalized consent that unblocks an EU recipient', async () => {
    const store = createMemoryComplianceStore()
    expect(assertRecipientEligible('eu@example.com', null, false, 'EU')?.code).toBe('unconfirmed-consent')

    await confirmDoubleOptIn(store, 'EU@example.com', 'EU', () => '2026-06-16T00:00:00.000Z')

    const consent = await store.getConsent('eu@example.com') // normalized lookup
    expect(consent?.doubleOptInConfirmed).toBe(true)
    expect(assertRecipientEligible('eu@example.com', consent, false, 'EU')).toBeNull()
  })

  it('errors clearly when an unregistered adapter is requested', () => {
    expect(() => getAdapter('loops', {})).toThrow(/No marketing adapter factory registered/)
  })
})
