import { describe, expect, it } from 'vitest'
import {
  defaultConsent,
  generatePrivacyPolicy,
  parseConsent,
  type ConsentState,
  type PrivacyPolicyInput,
} from './privacy.js'

const baseInput: PrivacyPolicyInput = {
  siteName: 'Acme',
  contactEmail: 'privacy@acme.test',
  jurisdiction: 'EU',
  dataCollected: ['email', 'usage analytics'],
  thirdParties: [{ name: 'AnalyticsCo', purpose: 'traffic measurement' }],
  cookies: [{ name: 'session', purpose: 'login', durationDays: 7 }],
}

describe('generatePrivacyPolicy', () => {
  it('includes site identity, contact, collected data, and cookies', () => {
    const md = generatePrivacyPolicy(baseInput)
    expect(md).toContain('Acme')
    expect(md).toContain('privacy@acme.test')
    expect(md).toContain('email')
    expect(md).toContain('usage analytics')
    expect(md).toContain('session')
    expect(md).toContain('traffic measurement')
  })

  it('omits optional sections when not provided', () => {
    const md = generatePrivacyPolicy({
      siteName: 'Solo',
      contactEmail: 'a@b.co',
      dataCollected: ['name'],
    })
    expect(md).toContain('Solo')
    expect(md).not.toContain('Third Parties')
  })
})

describe('parseConsent', () => {
  it('parses a valid consent blob', () => {
    const parsed = parseConsent({
      categories: { necessary: true, analytics: true, marketing: false, preferences: false },
      recordedAt: '2026-06-18T00:00:00Z',
      version: '1',
    })
    expect(parsed?.categories.analytics).toBe(true)
    expect(parsed?.recordedAt).toBe('2026-06-18T00:00:00Z')
  })

  it('returns null for garbage input without throwing', () => {
    for (const raw of [null, 42, 'x', {}, { categories: {} }]) {
      expect(parseConsent(raw)).toBeNull()
    }
  })

  it('parseConsent forces necessary:true even when the blob sets it false', () => {
    const parsed = parseConsent({
      categories: { necessary: false, analytics: true },
      recordedAt: '2026-06-18T00:00:00Z',
      version: '1',
    })
    expect(parsed?.categories.necessary).toBe(true)
  })

  it('drops unknown consent categories', () => {
    const parsed = parseConsent({
      categories: { necessary: true, analytics: false, tracking: true },
      recordedAt: '2026-06-18T00:00:00Z',
      version: '1',
    })
    expect(parsed).not.toBeNull()
    expect(Object.keys(parsed!.categories)).not.toContain('tracking')
  })

  it('returns null when recordedAt or version are missing or non-string', () => {
    expect(
      parseConsent({ categories: { necessary: true }, recordedAt: 1, version: '1' }),
    ).toBeNull()
    expect(parseConsent({ categories: { necessary: true }, recordedAt: 'x', version: 1 })).toBeNull()
    expect(parseConsent({ categories: { necessary: true } })).toBeNull()
  })
})

describe('defaultConsent', () => {
  it('opts out of non-necessary categories (privacy-by-default)', () => {
    const d = defaultConsent()
    expect(d.categories).toEqual({
      necessary: true,
      analytics: false,
      marketing: false,
      preferences: false,
    })
    expect(d.recordedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/)
    expect(d.version).toBeTruthy()
  })

  it('returns a fresh ConsentState shape each call', () => {
    const a: ConsentState = defaultConsent()
    const b = defaultConsent()
    expect(a).not.toBe(b)
    expect(a.categories).not.toBe(b.categories)
  })
})
