// =============================================================================
// Loeschfristen Module - Export & Report Generation
// JSON, CSV, Markdown-Compliance-Report und Browser-Download
// =============================================================================

import {
  LoeschfristPolicy,
  RETENTION_DRIVER_META,
  DELETION_METHOD_LABELS,
  STATUS_LABELS,
  TRIGGER_LABELS,
  formatRetentionDuration,
  getEffectiveDeletionTrigger,
} from './loeschfristen-types'

import {
  runComplianceCheck,
  ComplianceCheckResult,
  ComplianceIssueSeverity,
} from './loeschfristen-compliance'

// =============================================================================
// JSON EXPORT
// =============================================================================

interface PolicyExportEnvelope {
  exportDate: string
  version: string
  totalPolicies: number
  policies: LoeschfristPolicy[]
}

/**
 * Exportiert alle Policies als pretty-printed JSON.
 * Enthaelt Metadaten (Exportdatum, Version, Anzahl).
 */
export function exportPoliciesAsJSON(policies: LoeschfristPolicy[]): string {
  const exportData: PolicyExportEnvelope = {
    exportDate: new Date().toISOString(),
    version: '1.0',
    totalPolicies: policies.length,
    policies: policies,
  }
  return JSON.stringify(exportData, null, 2)
}

// =============================================================================
// CSV EXPORT
// =============================================================================

/**
 * Escapes a CSV field value according to RFC 4180.
 * Fields containing commas, double quotes, or newlines are wrapped in quotes.
 * Existing double quotes are doubled.
 */
function escapeCSVField(value: string): string {
  if (
    value.includes(',') ||
    value.includes('"') ||
    value.includes('\n') ||
    value.includes('\r') ||
    value.includes(';')
  ) {
    return `"${value.replace(/"/g, '""')}"`
  }
  return value
}

/**
 * Formats a date string to German locale format (DD.MM.YYYY).
 * Returns empty string for null/undefined/empty values.
 */
function formatDateDE(dateStr: string | null | undefined): string {
  if (!dateStr) return ''
  try {
    const date = new Date(dateStr)
    if (isNaN(date.getTime())) return ''
    return date.toLocaleDateString('de-DE', {
      day: '2-digit',
      month: '2-digit',
      year: 'numeric',
    })
  } catch {
    return ''
  }
}

/**
 * Exportiert alle Policies als CSV mit BOM fuer Excel-Kompatibilitaet.
 * Trennzeichen ist Semikolon (;) fuer deutschsprachige Excel-Versionen.
 */
export function exportPoliciesAsCSV(policies: LoeschfristPolicy[]): string {
  const BOM = '\uFEFF'
  const SEPARATOR = ';'

  const headers = [
    'LF-Nr.',
    'Datenobjekt',
    'Beschreibung',
    'Loeschtrigger',
    'Aufbewahrungstreiber',
    'Frist',
    'Startereignis',
    'Loeschmethode',
    'Verantwortlich',
    'Status',
    'Legal Hold aktiv',
    'Letzte Pruefung',
    'Naechste Pruefung',
  ]

  const rows: string[] = []

  // Header row
  rows.push(headers.map(escapeCSVField).join(SEPARATOR))

  // Data rows
  for (const policy of policies) {
    const effectiveTrigger = getEffectiveDeletionTrigger(policy)
    const triggerLabel = TRIGGER_LABELS[effectiveTrigger]

    const driverLabel = policy.retentionDriver
      ? RETENTION_DRIVER_META[policy.retentionDriver].label
      : ''

    const durationLabel = formatRetentionDuration(
      policy.retentionDuration,
      policy.retentionUnit
    )

    const methodLabel = DELETION_METHOD_LABELS[policy.deletionMethod]
    const statusLabel = STATUS_LABELS[policy.status]

    // Combine responsiblePerson and responsibleRole
    const responsible = [policy.responsiblePerson, policy.responsibleRole]
      .filter((s) => s.trim())
      .join(' / ')

    const legalHoldActive = policy.hasActiveLegalHold ? 'Ja' : 'Nein'

    const row = [
      policy.policyId,
      policy.dataObjectName,
      policy.description,
      triggerLabel,
      driverLabel,
      durationLabel,
      policy.startEvent,
      methodLabel,
      responsible || '-',
      statusLabel,
      legalHoldActive,
      formatDateDE(policy.lastReviewDate),
      formatDateDE(policy.nextReviewDate),
    ]

    rows.push(row.map(escapeCSVField).join(SEPARATOR))
  }

  return BOM + rows.join('\r\n')
}

// =============================================================================
// COMPLIANCE SUMMARY (MARKDOWN)
// =============================================================================

const SEVERITY_LABELS: Record<ComplianceIssueSeverity, string> = {
  CRITICAL: 'Kritisch',
  HIGH: 'Hoch',
  MEDIUM: 'Mittel',
  LOW: 'Niedrig',
}

const SEVERITY_EMOJI: Record<ComplianceIssueSeverity, string> = {
  CRITICAL: '[!!!]',
  HIGH: '[!!]',
  MEDIUM: '[!]',
  LOW: '[i]',
}

/**
 * Returns a textual rating based on the compliance score.
 */
function getScoreRating(score: number): string {
  if (score >= 90) return 'Ausgezeichnet'
  if (score >= 75) return 'Gut'
  if (score >= 50) return 'Verbesserungswuerdig'
  if (score >= 25) return 'Mangelhaft'
  return 'Kritisch'
}

/**
 * Generiert einen Markdown-formatierten Compliance-Bericht.
 * Enthaelt: Uebersicht, Score, Issue-Liste, Empfehlungen.
 */
export function generateComplianceSummary(
  policies: LoeschfristPolicy[],
  vvtDataCategories?: string[]
): string {
  const result: ComplianceCheckResult = runComplianceCheck(policies, vvtDataCategories)
  const now = new Date()

  const lines: string[] = []

  // Header
  lines.push('# Compliance-Bericht: Loeschfristen')
  lines.push('')
  lines.push(
    `**Erstellt am:** ${now.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })} um ${now.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })} Uhr`
  )
  lines.push('')

  // Overview
  lines.push('## Uebersicht')
  lines.push('')
  lines.push(`| Kennzahl | Wert |`)
  lines.push(`|----------|------|`)
  lines.push(`| Gepruefte Policies | ${result.stats.total} |`)
  lines.push(`| Bestanden | ${result.stats.passed} |`)
  lines.push(`| Beanstandungen | ${result.stats.failed} |`)
  lines.push(`| Compliance-Score | **${result.score}/100** (${getScoreRating(result.score)}) |`)
  lines.push('')

  // Severity breakdown
  lines.push('## Befunde nach Schweregrad')
  lines.push('')
  lines.push('| Schweregrad | Anzahl |')
  lines.push('|-------------|--------|')

  const severityOrder: ComplianceIssueSeverity[] = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']
  for (const severity of severityOrder) {
    const count = result.stats.bySeverity[severity]
    lines.push(`| ${SEVERITY_LABELS[severity]} | ${count} |`)
  }
  lines.push('')

  // Status distribution of policies
  const statusCounts: Record<string, number> = {}
  for (const policy of policies) {
    const label = STATUS_LABELS[policy.status]
    statusCounts[label] = (statusCounts[label] || 0) + 1
  }

  lines.push('## Policy-Status-Verteilung')
  lines.push('')
  lines.push('| Status | Anzahl |')
  lines.push('|--------|--------|')
  for (const [label, count] of Object.entries(statusCounts)) {
    lines.push(`| ${label} | ${count} |`)
  }
  lines.push('')

  // Issues list
  if (result.issues.length === 0) {
    lines.push('## Befunde')
    lines.push('')
    lines.push('Keine Beanstandungen gefunden. Alle Policies sind konform.')
    lines.push('')
  } else {
    lines.push('## Befunde')
    lines.push('')

    // Group issues by severity
    for (const severity of severityOrder) {
      const issuesForSeverity = result.issues.filter((i) => i.severity === severity)
      if (issuesForSeverity.length === 0) continue

      lines.push(`### ${SEVERITY_LABELS[severity]} ${SEVERITY_EMOJI[severity]}`)
      lines.push('')

      for (const issue of issuesForSeverity) {
        const policyRef =
          issue.policyId !== '-' ? ` (${issue.policyId})` : ''
        lines.push(`**${issue.title}**${policyRef}`)
        lines.push('')
        lines.push(`> ${issue.description}`)
        lines.push('')
        lines.push(`Empfehlung: ${issue.recommendation}`)
        lines.push('')
        lines.push('---')
        lines.push('')
      }
    }
  }

  // Recommendations summary
  lines.push('## Zusammenfassung der Empfehlungen')
  lines.push('')

  if (result.stats.bySeverity.CRITICAL > 0) {
    lines.push(
      `1. **Sofortmassnahmen erforderlich:** ${result.stats.bySeverity.CRITICAL} kritische(r) Befund(e) muessen umgehend behoben werden (Legal Hold-Konflikte).`
    )
  }
  if (result.stats.bySeverity.HIGH > 0) {
    lines.push(
      `${result.stats.bySeverity.CRITICAL > 0 ? '2' : '1'}. **Hohe Prioritaet:** ${result.stats.bySeverity.HIGH} Befund(e) mit hoher Prioritaet (fehlende Trigger/Rechtsgrundlagen) sollten zeitnah bearbeitet werden.`
    )
  }
  if (result.stats.bySeverity.MEDIUM > 0) {
    lines.push(
      `- **Mittlere Prioritaet:** ${result.stats.bySeverity.MEDIUM} Befund(e) betreffen ueberfaellige Pruefungen, fehlende Verantwortlichkeiten oder nicht abgedeckte Datenkategorien.`
    )
  }
  if (result.stats.bySeverity.LOW > 0) {
    lines.push(
      `- **Niedrige Prioritaet:** ${result.stats.bySeverity.LOW} Befund(e) betreffen veraltete Entwuerfe, die finalisiert oder archiviert werden sollten.`
    )
  }
  if (result.issues.length === 0) {
    lines.push(
      'Alle Policies sind konform. Stellen Sie sicher, dass die naechsten Pruefungstermine eingehalten werden.'
    )
  }
  lines.push('')

  // Footer
  lines.push('---')
  lines.push('')
  lines.push(
    '*Dieser Bericht wurde automatisch generiert und ersetzt keine rechtliche Beratung. Die Verantwortung fuer die DSGVO-Konformitaet liegt beim Verantwortlichen (Art. 4 Nr. 7 DSGVO).*'
  )

  return lines.join('\n')
}

// =============================================================================
// BROWSER DOWNLOAD UTILITY
// =============================================================================

/**
 * Loest einen Datei-Download im Browser aus.
 * Erstellt ein temporaeres Blob-URL und simuliert einen Link-Klick.
 *
 * @param content - Der Dateiinhalt als String
 * @param filename - Der gewuenschte Dateiname (z.B. "loeschfristen-export.json")
 * @param mimeType - Der MIME-Typ (z.B. "application/json", "text/csv;charset=utf-8")
 */
export function downloadFile(
  content: string,
  filename: string,
  mimeType: string
): void {
  const blob = new Blob([content], { type: mimeType })
  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)
}
