/**
 * SDK Export Utilities
 * Handles PDF and ZIP export of SDK state and documents
 */

import jsPDF from 'jspdf'
import JSZip from 'jszip'
import { SDKState, SDK_STEPS, getStepById } from './types'

// =============================================================================
// TYPES
// =============================================================================

export interface ExportOptions {
  includeEvidence?: boolean
  includeDocuments?: boolean
  includeRawData?: boolean
  language?: 'de' | 'en'
}

const DEFAULT_OPTIONS: ExportOptions = {
  includeEvidence: true,
  includeDocuments: true,
  includeRawData: true,
  language: 'de',
}

// =============================================================================
// LABELS (German)
// =============================================================================

const LABELS_DE = {
  title: 'AI Compliance SDK - Export',
  subtitle: 'Compliance-Dokumentation',
  generatedAt: 'Generiert am',
  page: 'Seite',
  summary: 'Zusammenfassung',
  progress: 'Fortschritt',
  phase1: 'Phase 1: Automatisches Compliance Assessment',
  phase2: 'Phase 2: Dokumentengenerierung',
  useCases: 'Use Cases',
  risks: 'Risiken',
  controls: 'Controls',
  requirements: 'Anforderungen',
  modules: 'Compliance-Module',
  evidence: 'Nachweise',
  checkpoints: 'Checkpoints',
  noData: 'Keine Daten vorhanden',
  status: 'Status',
  completed: 'Abgeschlossen',
  pending: 'Ausstehend',
  inProgress: 'In Bearbeitung',
  severity: 'Schweregrad',
  mitigation: 'Mitigation',
  description: 'Beschreibung',
  category: 'Kategorie',
  implementation: 'Implementierung',
}

// =============================================================================
// PDF EXPORT
// =============================================================================

function formatDate(date: Date | string | undefined): string {
  if (!date) return '-'
  const d = typeof date === 'string' ? new Date(date) : date
  return d.toLocaleDateString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function addHeader(doc: jsPDF, title: string, pageNum: number, totalPages: number): void {
  const pageWidth = doc.internal.pageSize.getWidth()

  // Header line
  doc.setDrawColor(147, 51, 234) // Purple
  doc.setLineWidth(0.5)
  doc.line(20, 15, pageWidth - 20, 15)

  // Title
  doc.setFontSize(10)
  doc.setTextColor(100)
  doc.text(title, 20, 12)

  // Page number
  doc.text(`${LABELS_DE.page} ${pageNum}/${totalPages}`, pageWidth - 40, 12)
}

function addFooter(doc: jsPDF, state: SDKState): void {
  const pageWidth = doc.internal.pageSize.getWidth()
  const pageHeight = doc.internal.pageSize.getHeight()

  // Footer line
  doc.setDrawColor(200)
  doc.setLineWidth(0.3)
  doc.line(20, pageHeight - 15, pageWidth - 20, pageHeight - 15)

  // Footer text
  doc.setFontSize(8)
  doc.setTextColor(150)
  doc.text(`Tenant: ${state.tenantId} | ${LABELS_DE.generatedAt}: ${formatDate(new Date())}`, 20, pageHeight - 10)
}

function addSectionTitle(doc: jsPDF, title: string, y: number): number {
  doc.setFontSize(14)
  doc.setTextColor(147, 51, 234) // Purple
  doc.setFont('helvetica', 'bold')
  doc.text(title, 20, y)
  doc.setFont('helvetica', 'normal')
  return y + 10
}

function addSubsectionTitle(doc: jsPDF, title: string, y: number): number {
  doc.setFontSize(11)
  doc.setTextColor(60)
  doc.setFont('helvetica', 'bold')
  doc.text(title, 25, y)
  doc.setFont('helvetica', 'normal')
  return y + 7
}

function addText(doc: jsPDF, text: string, x: number, y: number, maxWidth: number = 170): number {
  doc.setFontSize(10)
  doc.setTextColor(60)
  const lines = doc.splitTextToSize(text, maxWidth)
  doc.text(lines, x, y)
  return y + lines.length * 5
}

function checkPageBreak(doc: jsPDF, y: number, requiredSpace: number = 40): number {
  const pageHeight = doc.internal.pageSize.getHeight()
  if (y + requiredSpace > pageHeight - 25) {
    doc.addPage()
    return 30
  }
  return y
}

export async function exportToPDF(state: SDKState, options: ExportOptions = {}): Promise<Blob> {
  const opts = { ...DEFAULT_OPTIONS, ...options }
  const doc = new jsPDF()

  let y = 30
  const pageWidth = doc.internal.pageSize.getWidth()

  // ==========================================================================
  // Title Page
  // ==========================================================================

  // Logo/Title area
  doc.setFillColor(147, 51, 234)
  doc.rect(0, 0, pageWidth, 60, 'F')

  doc.setFontSize(24)
  doc.setTextColor(255)
  doc.setFont('helvetica', 'bold')
  doc.text(LABELS_DE.title, 20, 35)

  doc.setFontSize(14)
  doc.setFont('helvetica', 'normal')
  doc.text(LABELS_DE.subtitle, 20, 48)

  // Reset for content
  y = 80

  // Summary box
  doc.setDrawColor(200)
  doc.setFillColor(249, 250, 251)
  doc.roundedRect(20, y, pageWidth - 40, 50, 3, 3, 'FD')

  y += 15
  doc.setFontSize(12)
  doc.setTextColor(60)
  doc.text(`${LABELS_DE.generatedAt}: ${formatDate(new Date())}`, 30, y)

  y += 10
  doc.text(`Tenant ID: ${state.tenantId}`, 30, y)

  y += 10
  doc.text(`Version: ${state.version}`, 30, y)

  y += 10
  const completedSteps = state.completedSteps.length
  const totalSteps = SDK_STEPS.length
  doc.text(`${LABELS_DE.progress}: ${completedSteps}/${totalSteps} Schritte (${Math.round(completedSteps / totalSteps * 100)}%)`, 30, y)

  y += 30

  // Table of Contents
  y = addSectionTitle(doc, 'Inhaltsverzeichnis', y)

  const tocItems = [
    { title: 'Zusammenfassung', page: 2 },
    { title: 'Phase 1: Compliance Assessment', page: 3 },
    { title: 'Phase 2: Dokumentengenerierung', page: 4 },
    { title: 'Risiken & Controls', page: 5 },
    { title: 'Checkpoints', page: 6 },
  ]

  doc.setFontSize(10)
  doc.setTextColor(80)
  tocItems.forEach((item, idx) => {
    doc.text(`${idx + 1}. ${item.title}`, 25, y)
    doc.text(`${item.page}`, pageWidth - 30, y, { align: 'right' })
    y += 7
  })

  // ==========================================================================
  // Summary Page
  // ==========================================================================

  doc.addPage()
  y = 30

  y = addSectionTitle(doc, LABELS_DE.summary, y)

  // Progress overview
  doc.setFillColor(249, 250, 251)
  doc.roundedRect(20, y, pageWidth - 40, 40, 3, 3, 'F')

  y += 15
  const phase1Steps = SDK_STEPS.filter(s => s.phase === 1)
  const phase2Steps = SDK_STEPS.filter(s => s.phase === 2)
  const phase1Completed = phase1Steps.filter(s => state.completedSteps.includes(s.id)).length
  const phase2Completed = phase2Steps.filter(s => state.completedSteps.includes(s.id)).length

  doc.setFontSize(10)
  doc.setTextColor(60)
  doc.text(`${LABELS_DE.phase1}: ${phase1Completed}/${phase1Steps.length} ${LABELS_DE.completed}`, 30, y)
  y += 8
  doc.text(`${LABELS_DE.phase2}: ${phase2Completed}/${phase2Steps.length} ${LABELS_DE.completed}`, 30, y)

  y += 25

  // Key metrics
  y = addSubsectionTitle(doc, 'Kennzahlen', y)

  const metrics = [
    { label: 'Use Cases', value: state.useCases.length },
    { label: 'Risiken identifiziert', value: state.risks.length },
    { label: 'Controls definiert', value: state.controls.length },
    { label: 'Anforderungen', value: state.requirements.length },
    { label: 'Nachweise', value: state.evidence.length },
  ]

  metrics.forEach(metric => {
    doc.text(`${metric.label}: ${metric.value}`, 30, y)
    y += 7
  })

  // ==========================================================================
  // Use Cases
  // ==========================================================================

  y += 10
  y = checkPageBreak(doc, y)
  y = addSectionTitle(doc, LABELS_DE.useCases, y)

  if (state.useCases.length === 0) {
    y = addText(doc, LABELS_DE.noData, 25, y)
  } else {
    state.useCases.forEach((uc, idx) => {
      y = checkPageBreak(doc, y, 50)

      doc.setFillColor(249, 250, 251)
      doc.roundedRect(20, y - 5, pageWidth - 40, 35, 2, 2, 'F')

      doc.setFontSize(11)
      doc.setTextColor(40)
      doc.setFont('helvetica', 'bold')
      doc.text(`${idx + 1}. ${uc.name}`, 25, y + 5)
      doc.setFont('helvetica', 'normal')

      doc.setFontSize(9)
      doc.setTextColor(100)
      const ucStatus = uc.stepsCompleted === uc.steps.length ? LABELS_DE.completed : `${uc.stepsCompleted}/${uc.steps.length} Schritte`
      doc.text(`ID: ${uc.id} | ${LABELS_DE.status}: ${ucStatus}`, 25, y + 13)

      if (uc.description) {
        y = addText(doc, uc.description, 25, y + 21, 160)
      }

      y += 40
    })
  }

  // ==========================================================================
  // Risks
  // ==========================================================================

  doc.addPage()
  y = 30
  y = addSectionTitle(doc, LABELS_DE.risks, y)

  if (state.risks.length === 0) {
    y = addText(doc, LABELS_DE.noData, 25, y)
  } else {
    // Sort by severity
    const sortedRisks = [...state.risks].sort((a, b) => {
      const order = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 }
      return (order[a.severity] || 4) - (order[b.severity] || 4)
    })

    sortedRisks.forEach((risk, idx) => {
      y = checkPageBreak(doc, y, 45)

      // Severity color
      const severityColors: Record<string, [number, number, number]> = {
        CRITICAL: [220, 38, 38],
        HIGH: [234, 88, 12],
        MEDIUM: [234, 179, 8],
        LOW: [34, 197, 94],
      }
      const color = severityColors[risk.severity] || [100, 100, 100]

      doc.setFillColor(color[0], color[1], color[2])
      doc.rect(20, y - 3, 3, 30, 'F')

      doc.setFontSize(11)
      doc.setTextColor(40)
      doc.setFont('helvetica', 'bold')
      doc.text(`${idx + 1}. ${risk.title}`, 28, y + 5)
      doc.setFont('helvetica', 'normal')

      doc.setFontSize(9)
      doc.setTextColor(100)
      doc.text(`${LABELS_DE.severity}: ${risk.severity} | ${LABELS_DE.category}: ${risk.category}`, 28, y + 13)

      if (risk.description) {
        y = addText(doc, risk.description, 28, y + 21, 155)
      }

      if (risk.mitigation && risk.mitigation.length > 0) {
        y += 5
        doc.setFontSize(9)
        doc.setTextColor(34, 197, 94)
        doc.text(`${LABELS_DE.mitigation}: ${risk.mitigation.join(', ')}`, 28, y)
      }

      y += 15
    })
  }

  // ==========================================================================
  // Controls
  // ==========================================================================

  doc.addPage()
  y = 30
  y = addSectionTitle(doc, LABELS_DE.controls, y)

  if (state.controls.length === 0) {
    y = addText(doc, LABELS_DE.noData, 25, y)
  } else {
    state.controls.forEach((ctrl, idx) => {
      y = checkPageBreak(doc, y, 35)

      doc.setFillColor(249, 250, 251)
      doc.roundedRect(20, y - 5, pageWidth - 40, 28, 2, 2, 'F')

      doc.setFontSize(10)
      doc.setTextColor(40)
      doc.setFont('helvetica', 'bold')
      doc.text(`${idx + 1}. ${ctrl.name}`, 25, y + 5)
      doc.setFont('helvetica', 'normal')

      doc.setFontSize(9)
      doc.setTextColor(100)
      doc.text(`${LABELS_DE.category}: ${ctrl.category} | ${LABELS_DE.implementation}: ${ctrl.implementationStatus || 'Nicht definiert'}`, 25, y + 13)

      if (ctrl.description) {
        y = addText(doc, ctrl.description.substring(0, 150) + (ctrl.description.length > 150 ? '...' : ''), 25, y + 20, 160)
      }

      y += 35
    })
  }

  // ==========================================================================
  // Checkpoints
  // ==========================================================================

  doc.addPage()
  y = 30
  y = addSectionTitle(doc, LABELS_DE.checkpoints, y)

  const checkpointIds = Object.keys(state.checkpoints)

  if (checkpointIds.length === 0) {
    y = addText(doc, LABELS_DE.noData, 25, y)
  } else {
    checkpointIds.forEach((cpId) => {
      const cp = state.checkpoints[cpId]
      y = checkPageBreak(doc, y, 25)

      const statusColor = cp.passed ? [34, 197, 94] : [220, 38, 38]
      doc.setFillColor(statusColor[0], statusColor[1], statusColor[2])
      doc.circle(25, y + 2, 3, 'F')

      doc.setFontSize(10)
      doc.setTextColor(40)
      doc.text(cpId, 35, y + 5)

      doc.setFontSize(9)
      doc.setTextColor(100)
      doc.text(`${LABELS_DE.status}: ${cp.passed ? LABELS_DE.completed : LABELS_DE.pending}`, 35, y + 12)

      if (cp.errors && cp.errors.length > 0) {
        doc.setTextColor(220, 38, 38)
        doc.text(`Fehler: ${cp.errors.map(e => e.message).join(', ')}`, 35, y + 19)
        y += 7
      }

      y += 20
    })
  }

  // ==========================================================================
  // Add page numbers
  // ==========================================================================

  const pageCount = doc.getNumberOfPages()
  for (let i = 1; i <= pageCount; i++) {
    doc.setPage(i)
    if (i > 1) {
      addHeader(doc, LABELS_DE.title, i, pageCount)
    }
    addFooter(doc, state)
  }

  return doc.output('blob')
}

// =============================================================================
// ZIP EXPORT
// =============================================================================

export async function exportToZIP(state: SDKState, options: ExportOptions = {}): Promise<Blob> {
  const opts = { ...DEFAULT_OPTIONS, ...options }
  const zip = new JSZip()

  // Create folder structure
  const rootFolder = zip.folder('ai-compliance-sdk-export')
  if (!rootFolder) throw new Error('Failed to create ZIP folder')

  const phase1Folder = rootFolder.folder('phase1-assessment')
  const phase2Folder = rootFolder.folder('phase2-documents')
  const dataFolder = rootFolder.folder('data')

  // ==========================================================================
  // Main State JSON
  // ==========================================================================

  if (opts.includeRawData && dataFolder) {
    dataFolder.file('state.json', JSON.stringify(state, null, 2))
  }

  // ==========================================================================
  // README
  // ==========================================================================

  const readmeContent = `# AI Compliance SDK Export

Generated: ${formatDate(new Date())}
Tenant: ${state.tenantId}
Version: ${state.version}

## Folder Structure

- **phase1-assessment/**: Compliance Assessment Ergebnisse
  - use-cases.json: Alle Use Cases
  - risks.json: Identifizierte Risiken
  - controls.json: Definierte Controls
  - requirements.json: Compliance-Anforderungen

- **phase2-documents/**: Generierte Dokumente
  - dsfa.json: Datenschutz-Folgenabschaetzung
  - toms.json: Technische und organisatorische Massnahmen
  - vvt.json: Verarbeitungsverzeichnis
  - documents.json: Rechtliche Dokumente

- **data/**: Rohdaten
  - state.json: Kompletter SDK State

## Progress

Phase 1: ${SDK_STEPS.filter(s => s.phase === 1 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 1).length} completed
Phase 2: ${SDK_STEPS.filter(s => s.phase === 2 && state.completedSteps.includes(s.id)).length}/${SDK_STEPS.filter(s => s.phase === 2).length} completed

## Key Metrics

- Use Cases: ${state.useCases.length}
- Risks: ${state.risks.length}
- Controls: ${state.controls.length}
- Requirements: ${state.requirements.length}
- Evidence: ${state.evidence.length}
`

  rootFolder.file('README.md', readmeContent)

  // ==========================================================================
  // Phase 1 Files
  // ==========================================================================

  if (phase1Folder) {
    // Use Cases
    phase1Folder.file('use-cases.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.useCases.length,
      useCases: state.useCases,
    }, null, 2))

    // Risks
    phase1Folder.file('risks.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.risks.length,
      risks: state.risks,
      summary: {
        critical: state.risks.filter(r => r.severity === 'CRITICAL').length,
        high: state.risks.filter(r => r.severity === 'HIGH').length,
        medium: state.risks.filter(r => r.severity === 'MEDIUM').length,
        low: state.risks.filter(r => r.severity === 'LOW').length,
      },
    }, null, 2))

    // Controls
    phase1Folder.file('controls.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.controls.length,
      controls: state.controls,
    }, null, 2))

    // Requirements
    phase1Folder.file('requirements.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.requirements.length,
      requirements: state.requirements,
    }, null, 2))

    // Modules
    phase1Folder.file('modules.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.modules.length,
      modules: state.modules,
    }, null, 2))

    // Evidence
    if (opts.includeEvidence) {
      phase1Folder.file('evidence.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        count: state.evidence.length,
        evidence: state.evidence,
      }, null, 2))
    }

    // Checkpoints
    phase1Folder.file('checkpoints.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      checkpoints: state.checkpoints,
    }, null, 2))

    // Screening
    if (state.screening) {
      phase1Folder.file('screening.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        screening: state.screening,
      }, null, 2))
    }
  }

  // ==========================================================================
  // Phase 2 Files
  // ==========================================================================

  if (phase2Folder) {
    // DSFA
    if (state.dsfa) {
      phase2Folder.file('dsfa.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        dsfa: state.dsfa,
      }, null, 2))
    }

    // TOMs
    phase2Folder.file('toms.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.toms.length,
      toms: state.toms,
    }, null, 2))

    // VVT (Processing Activities)
    phase2Folder.file('vvt.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.vvt.length,
      processingActivities: state.vvt,
    }, null, 2))

    // Legal Documents
    if (opts.includeDocuments) {
      phase2Folder.file('documents.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        count: state.documents.length,
        documents: state.documents,
      }, null, 2))
    }

    // Cookie Banner Config
    if (state.cookieBanner) {
      phase2Folder.file('cookie-banner.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        config: state.cookieBanner,
      }, null, 2))
    }

    // Retention Policies
    phase2Folder.file('retention-policies.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.retentionPolicies.length,
      policies: state.retentionPolicies,
    }, null, 2))

    // AI Act Classification
    if (state.aiActClassification) {
      phase2Folder.file('ai-act-classification.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        classification: state.aiActClassification,
      }, null, 2))
    }

    // Obligations
    phase2Folder.file('obligations.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.obligations.length,
      obligations: state.obligations,
    }, null, 2))

    // Consent Records
    phase2Folder.file('consents.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.consents.length,
      consents: state.consents,
    }, null, 2))

    // DSR Config
    if (state.dsrConfig) {
      phase2Folder.file('dsr-config.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        config: state.dsrConfig,
      }, null, 2))
    }

    // Escalation Workflows
    phase2Folder.file('escalation-workflows.json', JSON.stringify({
      exportedAt: new Date().toISOString(),
      count: state.escalationWorkflows.length,
      workflows: state.escalationWorkflows,
    }, null, 2))
  }

  // ==========================================================================
  // Security Data
  // ==========================================================================

  if (dataFolder) {
    if (state.sbom) {
      dataFolder.file('sbom.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        sbom: state.sbom,
      }, null, 2))
    }

    if (state.securityIssues.length > 0) {
      dataFolder.file('security-issues.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        count: state.securityIssues.length,
        issues: state.securityIssues,
      }, null, 2))
    }

    if (state.securityBacklog.length > 0) {
      dataFolder.file('security-backlog.json', JSON.stringify({
        exportedAt: new Date().toISOString(),
        count: state.securityBacklog.length,
        backlog: state.securityBacklog,
      }, null, 2))
    }
  }

  // ==========================================================================
  // Generate PDF and include in ZIP
  // ==========================================================================

  try {
    const pdfBlob = await exportToPDF(state, options)
    const pdfArrayBuffer = await pdfBlob.arrayBuffer()
    rootFolder.file('compliance-report.pdf', pdfArrayBuffer)
  } catch (error) {
    console.error('Failed to generate PDF for ZIP:', error)
    // Continue without PDF
  }

  // Generate ZIP
  return zip.generateAsync({ type: 'blob', compression: 'DEFLATE' })
}

// =============================================================================
// EXPORT HELPER
// =============================================================================

export async function downloadExport(
  state: SDKState,
  format: 'json' | 'pdf' | 'zip',
  options: ExportOptions = {}
): Promise<void> {
  let blob: Blob
  let filename: string

  const timestamp = new Date().toISOString().slice(0, 10)

  switch (format) {
    case 'json':
      blob = new Blob([JSON.stringify(state, null, 2)], { type: 'application/json' })
      filename = `ai-compliance-sdk-${timestamp}.json`
      break

    case 'pdf':
      blob = await exportToPDF(state, options)
      filename = `ai-compliance-sdk-${timestamp}.pdf`
      break

    case 'zip':
      blob = await exportToZIP(state, options)
      filename = `ai-compliance-sdk-${timestamp}.zip`
      break

    default:
      throw new Error(`Unknown export format: ${format}`)
  }

  // Create download link
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}
