import { test, expect } from '@playwright/test'

/**
 * CMP Phase 3 + DSR Integration Tests
 *
 * Tests the complete CMP lifecycle including:
 * - Vendor-agnostic consent fields (consent_method, browser, os, etc.)
 * - Script/cookie tracking (scripts_blocked, scripts_released, cookies_set)
 * - Session ID tracking
 * - GeoIP via timezone mapping
 * - Vendor-level consent (vendor_consents dict)
 * - DSR scenarios: Art. 15 Auskunft, Art. 17 Löschung, Art. 20 Portabilität
 * - Email linking for DSR (device → user mapping)
 * - Admin modal features (vendor display, withdraw, email linking)
 */

const API_BASE = process.env.PLAYWRIGHT_API_URL || 'https://macmini:3007/api/sdk/v1/banner'
const TENANT_ID = '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e'
const HEADERS = {
  'Content-Type': 'application/json',
  'X-Tenant-ID': TENANT_ID,
}

const TS = Date.now()
const SITE_ID = `e2e-cmp3-${TS}`
const DEVICE_FP = `e2e-device-${TS}`

// ============================================================================
// 1. Vendor-Agnostic Consent Fields
// ============================================================================

test.describe('Vendor-Agnostic Consent Fields', () => {
  test('should store all 20+ fields on consent', async ({ request }) => {
    // Create site config first
    await request.post(`${API_BASE}/admin/sites`, {
      headers: HEADERS,
      data: { site_id: SITE_ID, site_name: 'E2E CMP Phase 3', site_url: 'https://test.example.com' },
    })

    // Record consent with all vendor-agnostic fields
    const res = await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: DEVICE_FP,
        categories: ['essential', 'functional', 'analytics'],
        vendors: ['Google Analytics', 'Matomo'],
        vendor_consents: { 'Google Analytics': true, 'Matomo': true, 'Facebook Pixel': false },
        user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) E2E-Test',
        consent_method: 'custom_selection',
        page_url: 'https://test.example.com/pricing',
        referrer: 'https://google.com',
        device_type: 'desktop',
        browser: 'Chrome/120.0',
        os: 'Mac OS X 10.15.7',
        screen_resolution: '1920x1080',
        consent_scope: 'domain',
        session_id: 'e2e-session-001',
        timezone: 'Europe/Berlin',
        scripts_blocked: [{ src: 'https://connect.facebook.net/fbevents.js', category: 'marketing' }],
        scripts_released: [{ src: 'https://www.googletagmanager.com/gtag/js', category: 'analytics' }],
        cookies_set: [
          { name: '_ga', domain: '.test.example.com', expiry_days: 730, category: 'analytics' },
          { name: 'bp_consent', domain: '.test.example.com', expiry_days: 365, category: 'essential' },
        ],
      },
    })

    expect(res.status()).toBe(200)
    const consent = await res.json()
    expect(consent.id).toBeTruthy()
    expect(consent.consent_method).toBe('custom_selection')
    expect(consent.device_type).toBe('desktop')
    expect(consent.browser).toBe('Chrome/120.0')
    expect(consent.os).toBe('Mac OS X 10.15.7')
    expect(consent.page_url).toBe('https://test.example.com/pricing')
    expect(consent.session_id).toBe('e2e-session-001')
    expect(consent.geo_country).toBe('DE') // Europe/Berlin → DE
    expect(consent.scripts_released).toHaveLength(1)
    expect(consent.cookies_set).toHaveLength(2)
    expect(consent.vendor_consents).toEqual({ 'Google Analytics': true, 'Matomo': true, 'Facebook Pixel': false })
  })

  test('should update consent on same fingerprint (upsert)', async ({ request }) => {
    const res = await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: DEVICE_FP,
        categories: ['essential'], // changed from all 3 to essential only
        vendors: [],
        consent_method: 'reject_all',
        page_url: 'https://test.example.com/settings',
        timezone: 'Europe/Vienna',
      },
    })

    expect(res.status()).toBe(200)
    const consent = await res.json()
    expect(consent.consent_method).toBe('reject_all')
    expect(consent.geo_country).toBe('AT') // Europe/Vienna → AT
    expect(consent.categories).toEqual(['essential'])
  })
})

// ============================================================================
// 2. DSR Scenarios — Art. 15 Auskunft
// ============================================================================

test.describe('DSR — Art. 15 Auskunftsrecht', () => {
  const DSR_EMAIL = `dsr-user-${TS}@example.com`
  const DSR_DEVICE_1 = `dsr-desktop-${TS}`
  const DSR_DEVICE_2 = `dsr-mobile-${TS}`

  test.beforeAll(async ({ request }) => {
    // Scenario: User visited website from 2 devices, then linked their email

    // Device 1: Desktop consent
    await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: DSR_DEVICE_1,
        categories: ['essential', 'analytics'],
        consent_method: 'accept_all',
        device_type: 'desktop',
        browser: 'Firefox/121.0',
        page_url: 'https://test.example.com/',
        timezone: 'Europe/Berlin',
      },
    })

    // Device 2: Mobile consent
    await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: DSR_DEVICE_2,
        categories: ['essential'],
        consent_method: 'reject_all',
        device_type: 'mobile',
        browser: 'Safari/17.0',
        page_url: 'https://test.example.com/pricing',
        timezone: 'Europe/Berlin',
      },
    })

    // User logs in and links email to both devices
    await request.post(`${API_BASE}/consent/link-email`, {
      headers: HEADERS,
      data: { site_id: SITE_ID, device_fingerprint: DSR_DEVICE_1, email: DSR_EMAIL },
    })
    await request.post(`${API_BASE}/consent/link-email`, {
      headers: HEADERS,
      data: { site_id: SITE_ID, device_fingerprint: DSR_DEVICE_2, email: DSR_EMAIL },
    })
  })

  test('Art. 15 — should find all consents by email', async ({ request }) => {
    const res = await request.get(`${API_BASE}/consent/by-email/${DSR_EMAIL}`, { headers: HEADERS })
    expect(res.status()).toBe(200)
    const consents = await res.json()
    expect(consents).toHaveLength(2)
    expect(consents.map((c: { device_fingerprint: string }) => c.device_fingerprint).sort()).toEqual(
      [DSR_DEVICE_1, DSR_DEVICE_2].sort()
    )
  })

  test('Art. 15/20 — should export all consent data for DSR', async ({ request }) => {
    const res = await request.get(`${API_BASE}/consent/dsr-export/${DSR_EMAIL}`, { headers: HEADERS })
    expect(res.status()).toBe(200)
    const exportData = await res.json()
    expect(exportData.consents).toHaveLength(2)
    expect(exportData.audit_trail.length).toBeGreaterThan(0)
  })

  test('Art. 17 — should delete all consents by email (erasure)', async ({ request }) => {
    const res = await request.delete(`${API_BASE}/consent/by-email/${DSR_EMAIL}`, { headers: HEADERS })
    expect(res.status()).toBe(200)
    const result = await res.json()
    expect(result.deleted_count).toBe(2)

    // Verify deletion
    const check = await request.get(`${API_BASE}/consent/by-email/${DSR_EMAIL}`, { headers: HEADERS })
    const remaining = await check.json()
    expect(remaining).toHaveLength(0)
  })
})

// ============================================================================
// 3. DSR Scenarios — Cookie Banner User (anonymous)
// ============================================================================

test.describe('DSR — Anonymous Cookie Banner User', () => {
  const ANON_DEVICE = `anon-user-${TS}`

  test.beforeAll(async ({ request }) => {
    await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: ANON_DEVICE,
        categories: ['essential', 'functional'],
        consent_method: 'custom_selection',
        device_type: 'tablet',
        browser: 'Chrome/120.0',
      },
    })
  })

  test('should export consent by device fingerprint', async ({ request }) => {
    const res = await request.get(
      `${API_BASE}/consent/export?site_id=${SITE_ID}&device_fingerprint=${ANON_DEVICE}`,
      { headers: HEADERS }
    )
    expect(res.status()).toBe(200)
    const data = await res.json()
    expect(data.device_fingerprint).toBe(ANON_DEVICE)
    expect(data.consents).toHaveLength(1)
    expect(data.audit_trail.length).toBeGreaterThan(0)
  })

  test('should withdraw consent by ID', async ({ request }) => {
    // Get consent ID first
    const getRes = await request.get(
      `${API_BASE}/consent?site_id=${SITE_ID}&device_fingerprint=${ANON_DEVICE}`,
      { headers: HEADERS }
    )
    const { consent } = await getRes.json()
    expect(consent).toBeTruthy()

    // Withdraw
    const delRes = await request.delete(`${API_BASE}/consent/${consent.id}`, { headers: HEADERS })
    expect(delRes.status()).toBe(200)

    // Verify
    const checkRes = await request.get(
      `${API_BASE}/consent?site_id=${SITE_ID}&device_fingerprint=${ANON_DEVICE}`,
      { headers: HEADERS }
    )
    const result = await checkRes.json()
    expect(result.has_consent).toBe(false)
  })
})

// ============================================================================
// 4. DSR Scenarios — Login User (Customer) who also used Cookie Banner
// ============================================================================

test.describe('DSR — Customer with Banner + Login', () => {
  const CUSTOMER_EMAIL = `customer-${TS}@company.com`
  const CUSTOMER_DEVICE = `customer-device-${TS}`

  test('full lifecycle: consent → login → link → Art.15 → Art.17', async ({ request }) => {
    // Step 1: Anonymous visit → cookie consent
    const consentRes = await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: CUSTOMER_DEVICE,
        categories: ['essential', 'analytics'],
        consent_method: 'accept_all',
        device_type: 'desktop',
        browser: 'Edge/120.0',
        page_url: 'https://test.example.com/',
        timezone: 'Europe/Zurich',
        scripts_released: [{ src: 'https://cdn.matomo.cloud/test.js', category: 'analytics' }],
        cookies_set: [{ name: '_pk_id', domain: '.test.example.com', expiry_days: 393, category: 'analytics' }],
      },
    })
    expect(consentRes.status()).toBe(200)
    const consent = await consentRes.json()
    expect(consent.geo_country).toBe('CH') // Europe/Zurich → CH

    // Step 2: Customer logs in → email linked
    const linkRes = await request.post(`${API_BASE}/consent/link-email`, {
      headers: HEADERS,
      data: { site_id: SITE_ID, device_fingerprint: CUSTOMER_DEVICE, email: CUSTOMER_EMAIL },
    })
    expect(linkRes.status()).toBe(200)

    // Step 3: Art. 15 — Customer requests their data
    const exportRes = await request.get(`${API_BASE}/consent/dsr-export/${CUSTOMER_EMAIL}`, { headers: HEADERS })
    expect(exportRes.status()).toBe(200)
    const exportData = await exportRes.json()
    expect(exportData.consents.length).toBeGreaterThan(0)
    expect(exportData.audit_trail.length).toBeGreaterThan(0)

    // Verify export contains all consent details
    const exported = exportData.consents[0]
    expect(exported.categories).toContain('analytics')
    expect(exported.linked_email).toBe(CUSTOMER_EMAIL)

    // Step 4: Art. 17 — Customer requests erasure
    const deleteRes = await request.delete(`${API_BASE}/consent/by-email/${CUSTOMER_EMAIL}`, { headers: HEADERS })
    expect(deleteRes.status()).toBe(200)

    // Step 5: Verify complete erasure
    const verifyRes = await request.get(`${API_BASE}/consent/by-email/${CUSTOMER_EMAIL}`, { headers: HEADERS })
    const remaining = await verifyRes.json()
    expect(remaining).toHaveLength(0)
  })
})

// ============================================================================
// 5. Admin Dashboard Integration
// ============================================================================

test.describe('Admin Dashboard — Consent Management', () => {
  const ADMIN_DEVICE = `admin-test-${TS}`

  test.beforeAll(async ({ request }) => {
    await request.post(`${API_BASE}/consent`, {
      headers: HEADERS,
      data: {
        site_id: SITE_ID,
        device_fingerprint: ADMIN_DEVICE,
        categories: ['essential', 'functional', 'analytics'],
        vendors: ['Matomo'],
        vendor_consents: { Matomo: true },
        consent_method: 'accept_all',
        device_type: 'desktop',
        browser: 'Chrome/121.0',
        os: 'Windows NT 10.0',
        screen_resolution: '2560x1440',
        page_url: 'https://test.example.com/dashboard',
        session_id: 'admin-session-001',
        timezone: 'Europe/Berlin',
      },
    })
  })

  test('should list consents with new fields', async ({ request }) => {
    const res = await request.get(`${API_BASE}/admin/consents?site_id=${SITE_ID}`, { headers: HEADERS })
    expect(res.status()).toBe(200)
    const data = await res.json()
    expect(data.total).toBeGreaterThan(0)

    const consent = data.consents.find((c: { device_fingerprint: string }) => c.device_fingerprint === ADMIN_DEVICE)
    expect(consent).toBeTruthy()
    expect(consent.consent_method).toBe('accept_all')
    expect(consent.device_type).toBe('desktop')
    expect(consent.browser).toBe('Chrome/121.0')
    expect(consent.os).toBe('Windows NT 10.0')
    expect(consent.screen_resolution).toBe('2560x1440')
    expect(consent.session_id).toBe('admin-session-001')
    expect(consent.geo_country).toBe('DE')
    expect(consent.vendor_consents).toEqual({ Matomo: true })
  })

  test('should show site stats with category acceptance', async ({ request }) => {
    const res = await request.get(`${API_BASE}/admin/stats/${SITE_ID}`, { headers: HEADERS })
    expect(res.status()).toBe(200)
    const stats = await res.json()
    expect(stats.total_consents).toBeGreaterThan(0)
    expect(stats.category_acceptance).toBeTruthy()
    expect(stats.category_acceptance.essential).toBeTruthy()
    expect(stats.category_acceptance.essential.rate).toBeGreaterThan(0)
  })
})

// ============================================================================
// 6. Cleanup
// ============================================================================

test.describe('Cleanup', () => {
  test('should delete test site config', async ({ request }) => {
    const res = await request.delete(`${API_BASE}/admin/sites/${SITE_ID}`, { headers: HEADERS })
    expect(res.status()).toBe(204)
  })
})
