// =============================================================================
// Control Library Loader
// Barrel re-exporting all category controls and providing loader functions.
// Data is split into categories/ subdirectory — each file <500 LOC.
// =============================================================================

import {
  ControlLibraryEntry,
  ControlCategory,
  ControlApplicability,
  ConditionOperator,
  ReviewFrequency,
  ControlPriority,
  ControlComplexity,
  LocalizedString,
  FrameworkMapping,
  ApplicabilityCondition,
} from '../types'

import { CATEGORY_MAP } from './categories/category-map'
import { ACCESS_CONTROLS } from './categories/access'
import { TRANSFER_INPUT_CONTROLS } from './categories/transfer-input'
import { ORDER_AVAILABILITY_CONTROLS } from './categories/order-availability'
import { SEPARATION_ENCRYPTION_CONTROLS } from './categories/separation-encryption'
import { PSEUDONYMIZATION_CONTROLS } from './categories/pseudonymization'
import { RESILIENCE_RECOVERY_CONTROLS } from './categories/resilience-recovery'
import { REVIEW_CONTROLS } from './categories/review'

// Re-export raw types for consumers that import them from here
export type {
  ControlLibraryEntry,
  ControlCategory,
  ControlApplicability,
  ConditionOperator,
  ReviewFrequency,
  ControlPriority,
  ControlComplexity,
  LocalizedString,
  FrameworkMapping,
  ApplicabilityCondition,
}

// =============================================================================
// PARSED CONTROL LIBRARY TYPE
// =============================================================================

export interface ControlLibrary {
  metadata: {
    version: string
    lastUpdated: string
    totalControls: number
  }
  categories: Map<
    ControlCategory,
    { name: LocalizedString; gdprReference: string }
  >
  controls: ControlLibraryEntry[]
}

// =============================================================================
// ASSEMBLED CONTROL LIBRARY DATA
// =============================================================================

const ALL_CONTROLS: ControlLibraryEntry[] = [
  ...ACCESS_CONTROLS,
  ...TRANSFER_INPUT_CONTROLS,
  ...ORDER_AVAILABILITY_CONTROLS,
  ...SEPARATION_ENCRYPTION_CONTROLS,
  ...PSEUDONYMIZATION_CONTROLS,
  ...RESILIENCE_RECOVERY_CONTROLS,
  ...REVIEW_CONTROLS,
]

const CONTROL_LIBRARY_DATA: ControlLibrary = {
  metadata: {
    version: '1.1.0',
    lastUpdated: '2026-03-19',
    totalControls: 88,
  },
  categories: CATEGORY_MAP,
  controls: ALL_CONTROLS,
}

// =============================================================================
// LOADER FUNCTIONS
// =============================================================================

let cachedLibrary: ControlLibrary | null = null

/**
 * Get the control library (singleton with embedded data)
 */
export function getControlLibrary(): ControlLibrary {
  if (!cachedLibrary) {
    cachedLibrary = CONTROL_LIBRARY_DATA
  }
  return cachedLibrary
}

/**
 * Get all controls from the library
 */
export function getAllControls(): ControlLibraryEntry[] {
  return getControlLibrary().controls
}

/**
 * Get a control by ID
 */
export function getControlById(id: string): ControlLibraryEntry | undefined {
  return getAllControls().find((control) => control.id === id)
}

/**
 * Get controls by category
 */
export function getControlsByCategory(
  category: ControlCategory
): ControlLibraryEntry[] {
  return getAllControls().filter((control) => control.category === category)
}

/**
 * Get controls by type (TECHNICAL or ORGANIZATIONAL)
 */
export function getControlsByType(
  type: 'TECHNICAL' | 'ORGANIZATIONAL'
): ControlLibraryEntry[] {
  return getAllControls().filter((control) => control.type === type)
}

/**
 * Get controls by priority
 */
export function getControlsByPriority(
  priority: ControlPriority
): ControlLibraryEntry[] {
  return getAllControls().filter((control) => control.priority === priority)
}

/**
 * Get controls by tag
 */
export function getControlsByTag(tag: string): ControlLibraryEntry[] {
  return getAllControls().filter((control) => control.tags.includes(tag))
}

/**
 * Get all unique tags from controls
 */
export function getAllTags(): string[] {
  const tags = new Set<string>()
  getAllControls().forEach((control) => {
    control.tags.forEach((tag) => tags.add(tag))
  })
  return Array.from(tags).sort()
}

/**
 * Get category metadata
 */
export function getCategoryMetadata(
  category: ControlCategory
): { name: LocalizedString; gdprReference: string } | undefined {
  return getControlLibrary().categories.get(category)
}

/**
 * Get all categories
 */
export function getAllCategories(): ControlCategory[] {
  return Array.from(getControlLibrary().categories.keys())
}

/**
 * Get categories with metadata (alias for API compatibility)
 */
export function getCategories(): Array<{
  id: ControlCategory
  name: LocalizedString
  gdprReference: string
}> {
  const library = getControlLibrary()
  const result: Array<{ id: ControlCategory; name: LocalizedString; gdprReference: string }> = []
  library.categories.forEach((metadata, id) => {
    result.push({
      id,
      name: metadata.name,
      gdprReference: metadata.gdprReference,
    })
  })
  return result
}

/**
 * Get library metadata
 */
export function getLibraryMetadata(): {
  version: string
  lastUpdated: string
  totalControls: number
} {
  return getControlLibrary().metadata
}

/**
 * Search controls by text (searches name and description in both languages)
 */
export function searchControls(
  query: string,
  language: 'de' | 'en' = 'de'
): ControlLibraryEntry[] {
  const lowerQuery = query.toLowerCase()
  return getAllControls().filter((control) => {
    const name = control.name[language].toLowerCase()
    const description = control.description[language].toLowerCase()
    const code = control.code.toLowerCase()
    return (
      name.includes(lowerQuery) ||
      description.includes(lowerQuery) ||
      code.includes(lowerQuery)
    )
  })
}

/**
 * Get controls by framework mapping
 */
export function getControlsByFramework(
  framework: string
): ControlLibraryEntry[] {
  return getAllControls().filter((control) =>
    control.mappings.some((m) => m.framework === framework)
  )
}

/**
 * Get controls count by category
 */
export function getControlsCountByCategory(): Map<ControlCategory, number> {
  const counts = new Map<ControlCategory, number>()
  getAllCategories().forEach((category) => {
    counts.set(category, getControlsByCategory(category).length)
  })
  return counts
}
