/**
 * Controls Library
 *
 * Standard controls for vendor and processing activity compliance.
 * Data is split by domain into sibling files — each <500 LOC.
 * This file re-assembles them and provides all helper functions.
 */

import { Control, ControlDomain, ReviewFrequency, LocalizedText } from '../types'

import { TRANSFER_CONTROLS, AUDIT_CONTROLS } from './transfer-audit'
import { DELETION_CONTROLS, INCIDENT_CONTROLS } from './deletion-incident'
import { SUBPROCESSOR_CONTROLS, TOM_CONTROLS } from './subprocessor-tom'
import { CONTRACT_CONTROLS, DATA_SUBJECT_CONTROLS } from './contract-data-subject'
import { SECURITY_CONTROLS, GOVERNANCE_CONTROLS } from './security-governance'

// ==========================================
// ASSEMBLED CONTROLS LIBRARY
// ==========================================

export const CONTROLS_LIBRARY: Control[] = [
  ...TRANSFER_CONTROLS,
  ...AUDIT_CONTROLS,
  ...DELETION_CONTROLS,
  ...INCIDENT_CONTROLS,
  ...SUBPROCESSOR_CONTROLS,
  ...TOM_CONTROLS,
  ...CONTRACT_CONTROLS,
  ...DATA_SUBJECT_CONTROLS,
  ...SECURITY_CONTROLS,
  ...GOVERNANCE_CONTROLS,
]

// ==========================================
// HELPER FUNCTIONS
// ==========================================

/**
 * Get all controls
 */
export function getAllControls(): Control[] {
  return CONTROLS_LIBRARY
}

/**
 * Get controls by domain
 */
export function getControlsByDomain(domain: ControlDomain): Control[] {
  return CONTROLS_LIBRARY.filter((c) => c.domain === domain)
}

/**
 * Get control by ID
 */
export function getControlById(id: string): Control | undefined {
  return CONTROLS_LIBRARY.find((c) => c.id === id)
}

/**
 * Get required controls
 */
export function getRequiredControls(): Control[] {
  return CONTROLS_LIBRARY.filter((c) => c.isRequired)
}

/**
 * Get controls by frequency
 */
export function getControlsByFrequency(frequency: ReviewFrequency): Control[] {
  return CONTROLS_LIBRARY.filter((c) => c.defaultFrequency === frequency)
}

/**
 * Get controls applicable to vendors
 */
export function getVendorControls(): Control[] {
  return CONTROLS_LIBRARY.filter((c) =>
    ['TRANSFER', 'AUDIT', 'DELETION', 'INCIDENT', 'SUBPROCESSOR', 'TOM', 'CONTRACT', 'DATA_SUBJECT', 'SECURITY', 'GOVERNANCE'].includes(c.domain)
  )
}

/**
 * Get controls applicable to processing activities
 */
export function getProcessingActivityControls(): Control[] {
  return CONTROLS_LIBRARY.filter((c) =>
    ['TOM', 'DATA_SUBJECT', 'GOVERNANCE', 'SECURITY'].includes(c.domain)
  )
}

/**
 * Group controls by domain
 */
export function getControlsGroupedByDomain(): Map<ControlDomain, Control[]> {
  const grouped = new Map<ControlDomain, Control[]>()

  for (const control of CONTROLS_LIBRARY) {
    const existing = grouped.get(control.domain) || []
    grouped.set(control.domain, [...existing, control])
  }

  return grouped
}

/**
 * Get domain metadata
 */
export function getControlDomainMeta(domain: ControlDomain): LocalizedText {
  const meta: Record<ControlDomain, LocalizedText> = {
    TRANSFER: { de: 'Drittlandtransfer', en: 'Third Country Transfer' },
    AUDIT: { de: 'Audit & Prüfung', en: 'Audit & Review' },
    DELETION: { de: 'Löschung', en: 'Deletion' },
    INCIDENT: { de: 'Incident Response', en: 'Incident Response' },
    SUBPROCESSOR: { de: 'Unterauftragnehmer', en: 'Sub-Processors' },
    TOM: { de: 'Technische/Org. Maßnahmen', en: 'Technical/Org. Measures' },
    CONTRACT: { de: 'Vertragliche Grundlagen', en: 'Contractual Basics' },
    DATA_SUBJECT: { de: 'Betroffenenrechte', en: 'Data Subject Rights' },
    SECURITY: { de: 'Sicherheit', en: 'Security' },
    GOVERNANCE: { de: 'Governance', en: 'Governance' },
  }

  return meta[domain]
}

/**
 * Calculate control coverage
 */
export function calculateControlCoverage(
  controlIds: string[],
  domain?: ControlDomain
): { covered: number; total: number; percentage: number } {
  const targetControls = domain
    ? getControlsByDomain(domain)
    : getRequiredControls()

  const covered = targetControls.filter((c) => controlIds.includes(c.id)).length

  return {
    covered,
    total: targetControls.length,
    percentage: targetControls.length > 0 ? Math.round((covered / targetControls.length) * 100) : 0,
  }
}
