/**
 * Integration Tests: Company Profile → Compliance Scope → VVT Generator
 *
 * Tests the complete data pipeline from Company Profile master data
 * through the Compliance Scope Engine to VVT activity generation.
 */
import { describe, it, expect } from 'vitest'
import {
  prefillFromCompanyProfile,
  exportToVVTAnswers,
  getAutoFilledScoringAnswers,
  SCOPE_QUESTION_BLOCKS,
} from '../compliance-scope-profiling'
import {
  generateActivities,
  PROFILING_QUESTIONS,
  DEPARTMENT_DATA_CATEGORIES,
  SCOPE_PREFILLED_VVT_QUESTIONS,
} from '../vvt-profiling'
import type { ScopeProfilingAnswer } from '../compliance-scope-types'

// Helper
function ans(questionId: string, value: unknown): ScopeProfilingAnswer {
  return { questionId, value } as ScopeProfilingAnswer
}

// =============================================================================
// 1. Company Profile → Scope Prefill
// =============================================================================

describe('CompanyProfile → Scope prefill', () => {
  it('prefills org_has_dsb when dpoName is set', () => {
    const profile = { dpoName: 'Max Mustermann' } as any
    const answers = prefillFromCompanyProfile(profile)
    expect(answers.find((a) => a.questionId === 'org_has_dsb')?.value).toBe(true)
  })

  it('does NOT prefill org_has_dsb when dpoName is empty', () => {
    const profile = { dpoName: '' } as any
    const answers = prefillFromCompanyProfile(profile)
    expect(answers.find((a) => a.questionId === 'org_has_dsb')).toBeUndefined()
  })

  it('maps offerings to prod_type correctly', () => {
    const profile = { offerings: ['WebApp', 'SaaS', 'API'] } as any
    const answers = prefillFromCompanyProfile(profile)
    const prodType = answers.find((a) => a.questionId === 'prod_type')
    expect(prodType?.value).toEqual(expect.arrayContaining(['webapp', 'saas', 'api']))
  })

  it('detects webshop in offerings', () => {
    const profile = { offerings: ['Webshop'] } as any
    const answers = prefillFromCompanyProfile(profile)
    expect(answers.find((a) => a.questionId === 'prod_webshop')?.value).toBe(true)
  })

  it('returns empty array when profile has no relevant data', () => {
    const profile = {} as any
    const answers = prefillFromCompanyProfile(profile)
    expect(answers).toEqual([])
  })
})

describe('CompanyProfile → Scope scoring answers', () => {
  it('maps employeeCount to org_employee_count', () => {
    const profile = { employeeCount: '50-249' } as any
    const answers = getAutoFilledScoringAnswers(profile)
    expect(answers.find((a) => a.questionId === 'org_employee_count')?.value).toBe('50-249')
  })

  it('maps industry to org_industry', () => {
    const profile = { industry: ['IT & Software', 'Finanzdienstleistungen'] } as any
    const answers = getAutoFilledScoringAnswers(profile)
    expect(answers.find((a) => a.questionId === 'org_industry')?.value).toBe(
      'IT & Software, Finanzdienstleistungen'
    )
  })

  it('maps annualRevenue to org_annual_revenue', () => {
    const profile = { annualRevenue: '1-10M' } as any
    const answers = getAutoFilledScoringAnswers(profile)
    expect(answers.find((a) => a.questionId === 'org_annual_revenue')?.value).toBe('1-10M')
  })

  it('maps businessModel to org_business_model', () => {
    const profile = { businessModel: 'B2B' } as any
    const answers = getAutoFilledScoringAnswers(profile)
    expect(answers.find((a) => a.questionId === 'org_business_model')?.value).toBe('B2B')
  })
})

// =============================================================================
// 2. Scope → VVT Answer Mapping (exportToVVTAnswers)
// =============================================================================

describe('Scope → VVT answer export', () => {
  it('maps scope questions with mapsToVVTQuestion property', () => {
    // Block 9: dk_dept_hr maps to dept_hr_categories
    const scopeAnswers: ScopeProfilingAnswer[] = [
      ans('dk_dept_hr', ['NAME', 'SALARY_DATA', 'HEALTH_DATA']),
    ]
    const vvtAnswers = exportToVVTAnswers(scopeAnswers)
    expect(vvtAnswers.dept_hr_categories).toEqual(['NAME', 'SALARY_DATA', 'HEALTH_DATA'])
  })

  it('maps multiple department data categories', () => {
    const scopeAnswers: ScopeProfilingAnswer[] = [
      ans('dk_dept_hr', ['NAME', 'BANK_ACCOUNT']),
      ans('dk_dept_finance', ['INVOICE_DATA', 'TAX_ID']),
      ans('dk_dept_marketing', ['EMAIL', 'TRACKING_DATA']),
    ]
    const vvtAnswers = exportToVVTAnswers(scopeAnswers)
    expect(vvtAnswers.dept_hr_categories).toEqual(['NAME', 'BANK_ACCOUNT'])
    expect(vvtAnswers.dept_finance_categories).toEqual(['INVOICE_DATA', 'TAX_ID'])
    expect(vvtAnswers.dept_marketing_categories).toEqual(['EMAIL', 'TRACKING_DATA'])
  })

  it('ignores scope questions without mapsToVVTQuestion', () => {
    const scopeAnswers: ScopeProfilingAnswer[] = [
      ans('vvt_has_vvt', true), // No mapsToVVTQuestion property
    ]
    const vvtAnswers = exportToVVTAnswers(scopeAnswers)
    expect(Object.keys(vvtAnswers)).toHaveLength(0)
  })

  it('handles empty scope answers', () => {
    const vvtAnswers = exportToVVTAnswers([])
    expect(vvtAnswers).toEqual({})
  })
})

// =============================================================================
// 3. Scope → VVT Profiling Prefill
// Note: prefillFromScopeAnswers() uses dynamic require('./compliance-scope-profiling')
// which doesn't resolve in vitest. We test the same pipeline by calling
// exportToVVTAnswers() directly (which is what prefillFromScopeAnswers wraps).
// =============================================================================

describe('Scope → VVT Profiling Prefill (via exportToVVTAnswers)', () => {
  it('converts scope answers to VVT ProfilingAnswers format', () => {
    const scopeAnswers: ScopeProfilingAnswer[] = [
      ans('dk_dept_hr', ['NAME', 'HEALTH_DATA']),
      ans('dk_dept_finance', ['BANK_ACCOUNT']),
    ]
    const exported = exportToVVTAnswers(scopeAnswers)
    // Same transformation as prefillFromScopeAnswers
    const profiling: Record<string, unknown> = {}
    for (const [key, value] of Object.entries(exported)) {
      if (value !== undefined && value !== null) profiling[key] = value
    }
    expect(profiling.dept_hr_categories).toEqual(['NAME', 'HEALTH_DATA'])
    expect(profiling.dept_finance_categories).toEqual(['BANK_ACCOUNT'])
  })

  it('filters out null/undefined values', () => {
    const scopeAnswers: ScopeProfilingAnswer[] = [ans('dk_dept_hr', null)]
    const exported = exportToVVTAnswers(scopeAnswers)
    const profiling: Record<string, unknown> = {}
    for (const [key, value] of Object.entries(exported)) {
      if (value !== undefined && value !== null) profiling[key] = value
    }
    expect(profiling.dept_hr_categories).toBeUndefined()
  })
})

// =============================================================================
// 4. VVT Generator — generateActivities
// =============================================================================

describe('generateActivities', () => {
  it('always generates 4 IT baseline activities', () => {
    const result = generateActivities({})
    const names = result.generatedActivities.map((a) => a.name)
    expect(result.generatedActivities.length).toBeGreaterThanOrEqual(4)
    // IT baselines are always added
    const itTemplates = result.generatedActivities.filter(
      (a) => a.businessFunction === 'it_operations'
    )
    expect(itTemplates.length).toBeGreaterThanOrEqual(4)
  })

  it('triggers HR templates when dept_hr=true', () => {
    const result = generateActivities({ dept_hr: true })
    const hrActivities = result.generatedActivities.filter(
      (a) => a.businessFunction === 'hr'
    )
    expect(hrActivities.length).toBeGreaterThanOrEqual(3) // mitarbeiter, gehalt, zeiterfassung
  })

  it('triggers finance templates when dept_finance=true', () => {
    const result = generateActivities({ dept_finance: true })
    const financeActivities = result.generatedActivities.filter(
      (a) => a.businessFunction === 'finance'
    )
    expect(financeActivities.length).toBeGreaterThanOrEqual(2) // buchhaltung, zahlungsverkehr
  })

  it('enriches activities with US cloud third-country transfer', () => {
    const result = generateActivities({ dept_hr: true, transfer_cloud_us: true })
    // Every activity should have a US third-country transfer
    for (const activity of result.generatedActivities) {
      expect(activity.thirdCountryTransfers.some((t) => t.country === 'US')).toBe(true)
    }
  })

  it('adds HEALTH_DATA to HR activities when data_health=true', () => {
    const result = generateActivities({ dept_hr: true, data_health: true })
    const hrActivities = result.generatedActivities.filter(
      (a) => a.businessFunction === 'hr'
    )
    expect(hrActivities.length).toBeGreaterThan(0)
    for (const hr of hrActivities) {
      expect(hr.personalDataCategories).toContain('HEALTH_DATA')
    }
  })

  it('calculates Art. 30 Abs. 5 exemption correctly', () => {
    // < 250 employees, no special categories → exempt
    const result1 = generateActivities({ org_employees: 50 })
    expect(result1.art30Abs5Exempt).toBe(true)

    // >= 250 employees → not exempt
    const result2 = generateActivities({ org_employees: 500 })
    expect(result2.art30Abs5Exempt).toBe(false)

    // < 250 but with special categories → not exempt
    const result3 = generateActivities({ org_employees: 50, data_health: true })
    expect(result3.art30Abs5Exempt).toBe(false)
  })

  it('generates unique VVT IDs for all activities', () => {
    const result = generateActivities({
      dept_hr: true,
      dept_finance: true,
      dept_sales: true,
      dept_marketing: true,
    })
    const ids = result.generatedActivities.map((a) => a.vvtId)
    const uniqueIds = new Set(ids)
    expect(uniqueIds.size).toBe(ids.length)
  })

  it('calculates coverage score > 0 for template-generated activities', () => {
    const result = generateActivities({ dept_hr: true })
    expect(result.coverageScore).toBeGreaterThan(0)
  })
})

// =============================================================================
// 5. Full Pipeline: Company Profile → Scope → VVT
// =============================================================================

describe('Full Pipeline: CompanyProfile → Scope → VVT Generation', () => {
  // Helper: replicate what prefillFromScopeAnswers does (avoiding dynamic require)
  function scopeToProfilingAnswers(
    scopeAnswers: ScopeProfilingAnswer[]
  ): Record<string, string | string[] | number | boolean> {
    const exported = exportToVVTAnswers(scopeAnswers)
    const profiling: Record<string, string | string[] | number | boolean> = {}
    for (const [key, value] of Object.entries(exported)) {
      if (value !== undefined && value !== null) {
        profiling[key] = value as string | string[] | number | boolean
      }
    }
    return profiling
  }

  it('complete flow: profile with DSB → scope prefill → VVT generation', () => {
    // Step 1: Company Profile
    const profile = {
      dpoName: 'Dr. Datenschutz',
      employeeCount: '50-249',
      industry: ['IT & Software'],
      offerings: ['WebApp', 'SaaS'],
    } as any

    // Step 2: Prefill scope from profile
    const profileAnswers = prefillFromCompanyProfile(profile)
    const scoringAnswers = getAutoFilledScoringAnswers(profile)

    // Simulate user answering scope questions + auto-prefilled from profile
    const userAnswers: ScopeProfilingAnswer[] = [
      // Block 8: departments
      ans('vvt_departments', ['personal', 'finanzen', 'it']),
      // Block 9: data categories per department
      ans('dk_dept_hr', ['NAME', 'ADDRESS', 'SALARY_DATA', 'HEALTH_DATA']),
      ans('dk_dept_finance', ['NAME', 'BANK_ACCOUNT', 'INVOICE_DATA', 'TAX_ID']),
      ans('dk_dept_it', ['USER_ACCOUNTS', 'LOG_DATA', 'DEVICE_DATA']),
      // Block 2: data types
      ans('data_art9', true),
      ans('data_minors', false),
    ]

    const allScopeAnswers = [...profileAnswers, ...scoringAnswers, ...userAnswers]

    // Step 3: Export to VVT format
    const vvtAnswers = exportToVVTAnswers(allScopeAnswers)
    expect(vvtAnswers.dept_hr_categories).toEqual([
      'NAME',
      'ADDRESS',
      'SALARY_DATA',
      'HEALTH_DATA',
    ])
    expect(vvtAnswers.dept_finance_categories).toEqual([
      'NAME',
      'BANK_ACCOUNT',
      'INVOICE_DATA',
      'TAX_ID',
    ])

    // Step 4: Prefill VVT profiling from scope (via direct export)
    const profilingAnswers = scopeToProfilingAnswers(allScopeAnswers)

    // Verify data survived the transformation
    expect(profilingAnswers.dept_hr_categories).toEqual([
      'NAME',
      'ADDRESS',
      'SALARY_DATA',
      'HEALTH_DATA',
    ])

    // Step 5: Generate VVT activities
    // Add department triggers that match Block 8 selections
    profilingAnswers.dept_hr = true
    profilingAnswers.dept_finance = true

    const result = generateActivities(profilingAnswers)

    // Verify activities were generated
    expect(result.generatedActivities.length).toBeGreaterThan(4) // 4 IT baseline + HR + Finance

    // Verify HR activities exist
    const hrActivities = result.generatedActivities.filter(
      (a) => a.businessFunction === 'hr'
    )
    expect(hrActivities.length).toBeGreaterThanOrEqual(3)

    // Verify finance activities exist
    const financeActivities = result.generatedActivities.filter(
      (a) => a.businessFunction === 'finance'
    )
    expect(financeActivities.length).toBeGreaterThanOrEqual(2)
  })

  it('end-to-end: departments selected in scope generate correct VVT activities', () => {
    // Simulate a complete scope session with department selections
    const scopeAnswers: ScopeProfilingAnswer[] = [
      // Block 2: data_art9 maps to data_health in VVT
      ans('data_art9', true),
      // Block 4: tech_third_country maps to transfer_cloud_us
      ans('tech_third_country', true),
      // Block 8: departments
      ans('vvt_departments', ['personal', 'marketing', 'kundenservice']),
      // Block 9: per-department data categories
      ans('dk_dept_hr', ['NAME', 'HEALTH_DATA', 'RELIGIOUS_BELIEFS']),
      ans('dk_dept_marketing', ['EMAIL', 'TRACKING_DATA', 'CONSENT_DATA']),
      ans('dk_dept_support', ['NAME', 'TICKET_DATA', 'COMMUNICATION_DATA']),
    ]

    // Transform to VVT answers
    const vvtAnswers = exportToVVTAnswers(scopeAnswers)

    // Verify Block 9 data categories are mapped correctly
    expect(vvtAnswers.dept_hr_categories).toEqual(['NAME', 'HEALTH_DATA', 'RELIGIOUS_BELIEFS'])
    expect(vvtAnswers.dept_marketing_categories).toEqual([
      'EMAIL',
      'TRACKING_DATA',
      'CONSENT_DATA',
    ])
    expect(vvtAnswers.dept_support_categories).toEqual([
      'NAME',
      'TICKET_DATA',
      'COMMUNICATION_DATA',
    ])

    // Verify the full pipeline using direct export
    const profilingAnswers = scopeToProfilingAnswers(scopeAnswers)
    expect(profilingAnswers.dept_hr_categories).toBeDefined()
    expect(profilingAnswers.dept_marketing_categories).toBeDefined()
    expect(profilingAnswers.dept_support_categories).toBeDefined()
  })
})

// =============================================================================
// 6. DEPARTMENT_DATA_CATEGORIES Integrity
// =============================================================================

describe('DEPARTMENT_DATA_CATEGORIES consistency', () => {
  it('all 12 departments are defined', () => {
    const expected = [
      'dept_hr',
      'dept_recruiting',
      'dept_finance',
      'dept_sales',
      'dept_marketing',
      'dept_support',
      'dept_it',
      'dept_recht',
      'dept_produktion',
      'dept_logistik',
      'dept_einkauf',
      'dept_facility',
    ]
    for (const dept of expected) {
      expect(DEPARTMENT_DATA_CATEGORIES[dept]).toBeDefined()
      expect(DEPARTMENT_DATA_CATEGORIES[dept].categories.length).toBeGreaterThan(0)
    }
  })

  it('every department has a label and icon', () => {
    for (const [, dept] of Object.entries(DEPARTMENT_DATA_CATEGORIES)) {
      expect(dept.label).toBeTruthy()
      expect(dept.icon).toBeTruthy()
    }
  })

  it('every category has id and label', () => {
    for (const [, dept] of Object.entries(DEPARTMENT_DATA_CATEGORIES)) {
      for (const cat of dept.categories) {
        expect(cat.id).toBeTruthy()
        expect(cat.label).toBeTruthy()
        expect(cat.info).toBeTruthy()
      }
    }
  })

  it('Art. 9 categories are correctly flagged', () => {
    const art9Categories = [
      { dept: 'dept_hr', id: 'HEALTH_DATA' },
      { dept: 'dept_hr', id: 'RELIGIOUS_BELIEFS' },
      { dept: 'dept_recruiting', id: 'HEALTH_DATA' },
      { dept: 'dept_recht', id: 'CRIMINAL_DATA' },
      { dept: 'dept_produktion', id: 'HEALTH_DATA' },
      { dept: 'dept_facility', id: 'HEALTH_DATA' },
    ]

    for (const { dept, id } of art9Categories) {
      const cat = DEPARTMENT_DATA_CATEGORIES[dept].categories.find((c) => c.id === id)
      expect(cat?.isArt9).toBe(true)
    }
  })
})

// =============================================================================
// 7. Block 9 ↔ VVT Mapping Integrity
// =============================================================================

describe('Block 9 Scope ↔ VVT question mapping', () => {
  it('every Block 9 question has mapsToVVTQuestion', () => {
    const block9 = SCOPE_QUESTION_BLOCKS.find((b) => b.id === 'datenkategorien_detail')
    expect(block9).toBeDefined()

    for (const q of block9!.questions) {
      expect(q.mapsToVVTQuestion).toBeTruthy()
      expect(q.mapsToVVTQuestion).toMatch(/^dept_\w+_categories$/)
    }
  })

  it('Block 9 question options match DEPARTMENT_DATA_CATEGORIES', () => {
    const block9 = SCOPE_QUESTION_BLOCKS.find((b) => b.id === 'datenkategorien_detail')
    expect(block9).toBeDefined()

    // dk_dept_hr should have same options as DEPARTMENT_DATA_CATEGORIES.dept_hr
    const hrQuestion = block9!.questions.find((q) => q.id === 'dk_dept_hr')
    expect(hrQuestion).toBeDefined()

    const expectedIds = DEPARTMENT_DATA_CATEGORIES.dept_hr.categories.map((c) => c.id)
    const actualIds = hrQuestion!.options!.map((o) => o.value)
    expect(actualIds).toEqual(expectedIds)
  })

  it('SCOPE_PREFILLED_VVT_QUESTIONS lists all cross-module questions', () => {
    expect(SCOPE_PREFILLED_VVT_QUESTIONS).toContain('org_industry')
    expect(SCOPE_PREFILLED_VVT_QUESTIONS).toContain('dept_hr')
    expect(SCOPE_PREFILLED_VVT_QUESTIONS).toContain('data_health')
    expect(SCOPE_PREFILLED_VVT_QUESTIONS).toContain('transfer_cloud_us')
    expect(SCOPE_PREFILLED_VVT_QUESTIONS.length).toBeGreaterThanOrEqual(15)
  })
})

// =============================================================================
// 8. Edge Cases
// =============================================================================

describe('Edge cases', () => {
  it('generateActivities with no answers still produces IT baselines', () => {
    const result = generateActivities({})
    expect(result.generatedActivities.length).toBe(4) // 4 IT baselines
    expect(result.art30Abs5Exempt).toBe(true) // 0 employees, no special categories
  })

  it('same template triggered by multiple questions is only generated once', () => {
    const result = generateActivities({
      dept_sales: true, // triggers sales-kundenverwaltung
      sys_crm: true, // also triggers sales-kundenverwaltung
    })

    const salesKunden = result.generatedActivities.filter((a) =>
      a.name.toLowerCase().includes('kundenverwaltung')
    )
    // Should be deduplicated (Set-based triggeredIds)
    expect(salesKunden.length).toBe(1)
  })

  it('empty department category selections produce valid but empty mappings', () => {
    const scopeAnswers: ScopeProfilingAnswer[] = [ans('dk_dept_hr', [])]
    const vvtAnswers = exportToVVTAnswers(scopeAnswers)
    expect(vvtAnswers.dept_hr_categories).toEqual([])
  })
})
