import { describe, expect, it } from 'vitest'
import type { Campaign } from './index.js'
import {
  applyTracking,
  buildRfc8058Headers,
  confirmDoubleOptIn,
  createMemoryComplianceStore,
  executeCompliantSend,
  recordTrackingConsent,
  validatePreSendLegalGate,
  type CampaignLegalContext,
} from './compliance.js'

const legalBase: CampaignLegalContext = {
  region: 'US',
  oneClickUnsubscribeUrl: 'https://example.com/unsub/one-click',
  legal: {
    spf: true,
    dkim: true,
    dmarc: true,
    physicalPostalAddress: '123 Main St, Springfield, IL 62701',
    advertisingLabel: 'Advertisement',
  },
}

const campaign: Campaign = {
  id: 'camp-1',
  name: 'Weekly',
  subject: 'Hello',
  html: '<html><body><p>Hi</p><a href="https://shop.example/item">Buy</a></body></html>',
  listIds: ['list-1'],
}

describe('validatePreSendLegalGate', () => {
  it('blocks a campaign missing a physical postal address', () => {
    expect(() =>
      validatePreSendLegalGate({
        ...legalBase,
        legal: { ...legalBase.legal, physicalPostalAddress: '' },
      }),
    ).toThrow(/physical postal address/)
  })

  it('blocks a campaign missing an advertising label', () => {
    expect(() =>
      validatePreSendLegalGate({
        ...legalBase,
        legal: { ...legalBase.legal, advertisingLabel: '' },
      }),
    ).toThrow(/advertising label/)
  })

  it('blocks an IL campaign missing the פרסומת label', () => {
    expect(() =>
      validatePreSendLegalGate({
        ...legalBase,
        region: 'IL',
        legal: { ...legalBase.legal, advertisingLabel: 'Advertisement' },
      }),
    ).toThrow(/פרסומת/)
  })
})

describe('executeCompliantSend', () => {
  it('refuses a suppressed address', async () => {
    const store = createMemoryComplianceStore({
      suppressed: [
        {
          email: 'blocked@example.com',
          reason: 'unsubscribe',
          suppressedAt: '2026-01-01T00:00:00.000Z',
        },
      ],
      consents: [
        {
          email: 'blocked@example.com',
          doubleOptInConfirmed: true,
          trackingConsent: false,
        },
      ],
    })

    const result = await executeCompliantSend(
      store,
      {
        campaignId: campaign.id,
        campaign,
        legal: legalBase,
        recipients: ['blocked@example.com'],
        trackingBaseUrl: 'https://track.example',
      },
      async () => {
        throw new Error('send should not run for suppressed recipient')
      },
    )

    expect(result.sent).toEqual([])
    expect(result.refused).toEqual([
      expect.objectContaining({ email: 'blocked@example.com', code: 'suppressed' }),
    ])
  })

  it('refuses an address whose double opt-in is not confirmed', async () => {
    const store = createMemoryComplianceStore()

    const result = await executeCompliantSend(
      store,
      {
        campaignId: campaign.id,
        campaign: { ...campaign, region: 'EU' },
        legal: { ...legalBase, region: 'EU' },
        recipients: ['new@example.com'],
        trackingBaseUrl: 'https://track.example',
      },
      async () => {
        throw new Error('send should not run without confirmed opt-in')
      },
    )

    expect(result.sent).toEqual([])
    expect(result.refused).toEqual([
      expect.objectContaining({ email: 'new@example.com', code: 'unconfirmed-consent' }),
    ])
  })

  it('omits tracking pixel and click redirect when no tracking-consent flag is recorded', async () => {
    const store = createMemoryComplianceStore()
    await confirmDoubleOptIn(store, 'reader@example.com', 'US')

    let capturedHtml = ''
    await executeCompliantSend(
      store,
      {
        campaignId: campaign.id,
        campaign,
        legal: legalBase,
        recipients: ['reader@example.com'],
        trackingBaseUrl: 'https://track.example',
      },
      async (message) => {
        capturedHtml = message.html
      },
    )

    expect(capturedHtml).not.toMatch(/\/o\//)
    expect(capturedHtml).toContain('href="https://shop.example/item"')
  })

  it('includes tracking pixel and click redirect when tracking consent is recorded', async () => {
    const store = createMemoryComplianceStore()
    await confirmDoubleOptIn(store, 'reader@example.com', 'US')
    await recordTrackingConsent(store, 'reader@example.com')

    let capturedHtml = ''
    await executeCompliantSend(
      store,
      {
        campaignId: campaign.id,
        campaign,
        legal: legalBase,
        recipients: ['reader@example.com'],
        trackingBaseUrl: 'https://track.example',
      },
      async (message) => {
        capturedHtml = message.html
      },
    )

    expect(capturedHtml).toMatch(/\/o\/camp-1\/reader%40example\.com/)
    expect(capturedHtml).toMatch(/\/c\/camp-1\/reader%40example\.com\?u=/)
  })

  it('auto-injects the RFC 8058 one-click unsubscribe header on a passing send', async () => {
    const store = createMemoryComplianceStore()
    await confirmDoubleOptIn(store, 'reader@example.com', 'US')

    let headers: Record<string, string> = {}
    await executeCompliantSend(
      store,
      {
        campaignId: campaign.id,
        campaign,
        legal: legalBase,
        recipients: ['reader@example.com'],
        trackingBaseUrl: 'https://track.example',
      },
      async (message) => {
        headers = message.headers
      },
    )

    expect(headers['List-Unsubscribe']).toBe(
      `<${legalBase.oneClickUnsubscribeUrl}>`,
    )
    expect(headers['List-Unsubscribe-Post']).toBe('List-Unsubscribe=One-Click')
  })
})

describe('confirmDoubleOptIn consent timestamp', () => {
  it('stamps confirmedAt from the injected clock (real wall-clock, not epoch-0)', async () => {
    const store = createMemoryComplianceStore()
    const clock = () => '2026-06-15T00:00:00.000Z'

    const record = await confirmDoubleOptIn(store, 'reader@example.com', 'EU', clock)

    expect(record.confirmedAt).toBe('2026-06-15T00:00:00.000Z')
    expect(record.confirmedAt).not.toBe(new Date(0).toISOString())
  })

  it('keeps the original confirmedAt on a second confirm with a different clock (idempotent first-stamp)', async () => {
    const store = createMemoryComplianceStore()
    const first = await confirmDoubleOptIn(
      store,
      'reader@example.com',
      'EU',
      () => '2026-06-15T00:00:00.000Z',
    )
    const second = await confirmDoubleOptIn(
      store,
      'reader@example.com',
      'EU',
      () => '2027-01-01T00:00:00.000Z',
    )

    expect(second.confirmedAt).toBe('2026-06-15T00:00:00.000Z')
    expect(second.confirmedAt).toBe(first.confirmedAt)
  })
})

describe('recordTrackingConsent consent timestamp', () => {
  it('stamps trackingConsentAt from the injected clock (real wall-clock, not epoch-0)', async () => {
    const store = createMemoryComplianceStore()
    const clock = () => '2026-06-15T00:00:00.000Z'

    const record = await recordTrackingConsent(store, 'reader@example.com', clock)

    expect(record.trackingConsentAt).toBe('2026-06-15T00:00:00.000Z')
    expect(record.trackingConsentAt).not.toBe(new Date(0).toISOString())
  })

  it('keeps the original trackingConsentAt on a second record with a different clock', async () => {
    const store = createMemoryComplianceStore()
    const first = await recordTrackingConsent(
      store,
      'reader@example.com',
      () => '2026-06-15T00:00:00.000Z',
    )
    const second = await recordTrackingConsent(
      store,
      'reader@example.com',
      () => '2027-01-01T00:00:00.000Z',
    )

    expect(second.trackingConsentAt).toBe('2026-06-15T00:00:00.000Z')
    expect(second.trackingConsentAt).toBe(first.trackingConsentAt)
  })
})

describe('applyTracking', () => {
  it('returns html unchanged when tracking consent is absent', () => {
    const html = '<a href="https://shop.example/item">x</a>'
    expect(
      applyTracking(html, {
        campaignId: 'c1',
        email: 'a@b.com',
        trackingBaseUrl: 'https://track.example',
        hasTrackingConsent: false,
      }),
    ).toBe(html)
  })
})

describe('buildRfc8058Headers', () => {
  it('builds List-Unsubscribe headers', () => {
    expect(buildRfc8058Headers('https://example.com/u')).toEqual({
      'List-Unsubscribe': '<https://example.com/u>',
      'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
    })
  })
})
