// =============================================================================
// TOM Generator ZIP Export
// Export complete TOM package as ZIP archive
// =============================================================================

import { TOMGeneratorState, DerivedTOM, EvidenceDocument } from '../types'
import { generateDOCXContent, DOCXExportOptions } from './docx'
import { generatePDFContent, PDFExportOptions } from './pdf'
import { getAllControls, getLibraryMetadata } from '../controls/loader'
import {
  generateReadme,
  groupTOMsByCategory,
  generateImplementationSummary,
  groupEvidenceByControl,
  generateRecommendationsMarkdown,
  generateMarkdownSummary,
  generateCSV,
} from './zip-helpers'

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

export interface ZIPExportOptions {
  language: 'de' | 'en'
  includeNotApplicable: boolean
  includeEvidence: boolean
  includeGapAnalysis: boolean
  includeControlLibrary: boolean
  includeRawData: boolean
  formats: Array<'json' | 'docx' | 'pdf'>
}

const DEFAULT_OPTIONS: ZIPExportOptions = {
  language: 'de',
  includeNotApplicable: false,
  includeEvidence: true,
  includeGapAnalysis: true,
  includeControlLibrary: true,
  includeRawData: true,
  formats: ['json', 'docx'],
}

// =============================================================================
// ZIP CONTENT STRUCTURE
// =============================================================================

export interface ZIPFileEntry {
  path: string
  content: string | Blob
  mimeType: string
}

/**
 * Generate all files for the ZIP archive
 */
export function generateZIPFiles(
  state: TOMGeneratorState,
  options: Partial<ZIPExportOptions> = {}
): ZIPFileEntry[] {
  const opts = { ...DEFAULT_OPTIONS, ...options }
  const files: ZIPFileEntry[] = []

  // README
  files.push({
    path: 'README.md',
    content: generateReadme(state, opts),
    mimeType: 'text/markdown',
  })

  // State JSON
  if (opts.includeRawData) {
    files.push({
      path: 'data/state.json',
      content: JSON.stringify(state, null, 2),
      mimeType: 'application/json',
    })
  }

  // Profile data
  files.push({
    path: 'data/profiles/company-profile.json',
    content: JSON.stringify(state.companyProfile, null, 2),
    mimeType: 'application/json',
  })

  files.push({
    path: 'data/profiles/data-profile.json',
    content: JSON.stringify(state.dataProfile, null, 2),
    mimeType: 'application/json',
  })

  files.push({
    path: 'data/profiles/architecture-profile.json',
    content: JSON.stringify(state.architectureProfile, null, 2),
    mimeType: 'application/json',
  })

  files.push({
    path: 'data/profiles/security-profile.json',
    content: JSON.stringify(state.securityProfile, null, 2),
    mimeType: 'application/json',
  })

  files.push({
    path: 'data/profiles/risk-profile.json',
    content: JSON.stringify(state.riskProfile, null, 2),
    mimeType: 'application/json',
  })

  // Derived TOMs
  files.push({
    path: 'data/toms/derived-toms.json',
    content: JSON.stringify(state.derivedTOMs, null, 2),
    mimeType: 'application/json',
  })

  // TOMs by category
  const tomsByCategory = groupTOMsByCategory(state.derivedTOMs)
  for (const [category, toms] of tomsByCategory.entries()) {
    files.push({
      path: `data/toms/by-category/${category.toLowerCase()}.json`,
      content: JSON.stringify(toms, null, 2),
      mimeType: 'application/json',
    })
  }

  // Required TOMs summary
  const requiredTOMs = state.derivedTOMs.filter(
    (tom) => tom.applicability === 'REQUIRED'
  )
  files.push({
    path: 'data/toms/required-toms.json',
    content: JSON.stringify(requiredTOMs, null, 2),
    mimeType: 'application/json',
  })

  // Implementation status summary
  const implementationSummary = generateImplementationSummary(state.derivedTOMs)
  files.push({
    path: 'data/toms/implementation-summary.json',
    content: JSON.stringify(implementationSummary, null, 2),
    mimeType: 'application/json',
  })

  // Evidence documents
  if (opts.includeEvidence && state.documents.length > 0) {
    files.push({
      path: 'data/evidence/documents.json',
      content: JSON.stringify(state.documents, null, 2),
      mimeType: 'application/json',
    })

    // Evidence by control
    const evidenceByControl = groupEvidenceByControl(state.documents)
    files.push({
      path: 'data/evidence/by-control.json',
      content: JSON.stringify(Object.fromEntries(evidenceByControl), null, 2),
      mimeType: 'application/json',
    })
  }

  // Gap Analysis
  if (opts.includeGapAnalysis && state.gapAnalysis) {
    files.push({
      path: 'data/gap-analysis/analysis.json',
      content: JSON.stringify(state.gapAnalysis, null, 2),
      mimeType: 'application/json',
    })

    // Missing controls details
    if (state.gapAnalysis.missingControls.length > 0) {
      files.push({
        path: 'data/gap-analysis/missing-controls.json',
        content: JSON.stringify(state.gapAnalysis.missingControls, null, 2),
        mimeType: 'application/json',
      })
    }

    // Recommendations
    if (state.gapAnalysis.recommendations.length > 0) {
      files.push({
        path: 'data/gap-analysis/recommendations.md',
        content: generateRecommendationsMarkdown(
          state.gapAnalysis.recommendations,
          opts.language
        ),
        mimeType: 'text/markdown',
      })
    }
  }

  // Control Library
  if (opts.includeControlLibrary) {
    const controls = getAllControls()
    const metadata = getLibraryMetadata()

    files.push({
      path: 'reference/control-library/metadata.json',
      content: JSON.stringify(metadata, null, 2),
      mimeType: 'application/json',
    })

    files.push({
      path: 'reference/control-library/all-controls.json',
      content: JSON.stringify(controls, null, 2),
      mimeType: 'application/json',
    })

    // Controls by category
    for (const category of new Set(controls.map((c) => c.category))) {
      const categoryControls = controls.filter((c) => c.category === category)
      files.push({
        path: `reference/control-library/by-category/${category.toLowerCase()}.json`,
        content: JSON.stringify(categoryControls, null, 2),
        mimeType: 'application/json',
      })
    }
  }

  // Export history
  if (state.exports.length > 0) {
    files.push({
      path: 'data/exports/history.json',
      content: JSON.stringify(state.exports, null, 2),
      mimeType: 'application/json',
    })
  }

  // DOCX content structure (if requested)
  if (opts.formats.includes('docx')) {
    const docxOptions: Partial<DOCXExportOptions> = {
      language: opts.language,
      includeNotApplicable: opts.includeNotApplicable,
      includeEvidence: opts.includeEvidence,
      includeGapAnalysis: opts.includeGapAnalysis,
    }
    const docxContent = generateDOCXContent(state, docxOptions)
    files.push({
      path: 'documents/tom-document-structure.json',
      content: JSON.stringify(docxContent, null, 2),
      mimeType: 'application/json',
    })
  }

  // PDF content structure (if requested)
  if (opts.formats.includes('pdf')) {
    const pdfOptions: Partial<PDFExportOptions> = {
      language: opts.language,
      includeNotApplicable: opts.includeNotApplicable,
      includeEvidence: opts.includeEvidence,
      includeGapAnalysis: opts.includeGapAnalysis,
    }
    const pdfContent = generatePDFContent(state, pdfOptions)
    files.push({
      path: 'documents/tom-document-structure-pdf.json',
      content: JSON.stringify(pdfContent, null, 2),
      mimeType: 'application/json',
    })
  }

  // Markdown summary
  files.push({
    path: 'documents/tom-summary.md',
    content: generateMarkdownSummary(state, opts),
    mimeType: 'text/markdown',
  })

  // CSV export for spreadsheet import
  files.push({
    path: 'documents/toms.csv',
    content: generateCSV(state.derivedTOMs, opts),
    mimeType: 'text/csv',
  })

  return files
}

// =============================================================================
// ZIP BLOB GENERATION
// Note: For production, use jszip library
// =============================================================================

/**
 * Generate a ZIP file as a Blob
 * This is a placeholder - in production, use jszip library
 */
export async function generateZIPBlob(
  state: TOMGeneratorState,
  options: Partial<ZIPExportOptions> = {}
): Promise<Blob> {
  const files = generateZIPFiles(state, options)

  // Create a simple JSON representation for now
  // In production, use JSZip library
  const manifest = {
    generated: new Date().toISOString(),
    files: files.map((f) => ({
      path: f.path,
      mimeType: f.mimeType,
      size: typeof f.content === 'string' ? f.content.length : 0,
    })),
  }

  const allContent = files
    .filter((f) => typeof f.content === 'string')
    .map((f) => `\n\n=== ${f.path} ===\n\n${f.content}`)
    .join('\n')

  const output = `TOM Export Package
Generated: ${manifest.generated}

Files:
${manifest.files.map((f) => `  - ${f.path} (${f.mimeType})`).join('\n')}

${allContent}`

  return new Blob([output], { type: 'application/zip' })
}

// =============================================================================
// FILENAME GENERATION
// =============================================================================

/**
 * Generate a filename for ZIP export
 */
export function generateZIPFilename(
  state: TOMGeneratorState,
  language: 'de' | 'en' = 'de'
): string {
  const companyName = state.companyProfile?.name?.replace(/[^a-zA-Z0-9]/g, '-') || 'unknown'
  const date = new Date().toISOString().split('T')[0]
  const prefix = language === 'de' ? 'TOMs-Export' : 'TOMs-Export'
  return `${prefix}-${companyName}-${date}.zip`
}

// =============================================================================
// EXPORT
// =============================================================================

// Types are exported at their definition site above
