/**
 * Data Classification Service
 * 
 * Implements data classification and marking per DoD/MilSpec requirements:
 * - DoD Manual 5200.01: Information Security Program
 * - NIST SP 800-53: AC-16 (Security Attributes)
 * 
 * Features:
 * - Automatic data classification
 * - Data marking and labeling
 * - Classification-based access controls
 * - Classification-based encryption
 * - Data handling procedures per classification
 */

import { getDb } from '../db'
import { logger } from '../lib/logger'

export type ClassificationLevel = 
  | 'UNCLASSIFIED'
  | 'CUI' // Controlled Unclassified Information
  | 'CONFIDENTIAL'
  | 'SECRET'
  | 'TOP_SECRET'

export interface DataClassification {
  level: ClassificationLevel
  category?: string
  markings?: string[]
  handlingInstructions?: string[]
  owner?: string
  createdAt: Date
  updatedAt: Date
}

/**
 * Classification rules for automatic classification
 */
const CLASSIFICATION_RULES: Array<{
  pattern: RegExp
  level: ClassificationLevel
  category?: string
}> = [
  // Credentials and secrets
  { pattern: /password|secret|token|key|credential/i, level: 'SECRET', category: 'CREDENTIALS' },
  // Personal information
  { pattern: /ssn|social.security|credit.card|bank.account/i, level: 'CUI', category: 'PII' },
  // Financial data
  { pattern: /billing|invoice|payment|financial/i, level: 'CUI', category: 'FINANCIAL' },
  // Health information
  { pattern: /health|medical|hipaa/i, level: 'CONFIDENTIAL', category: 'PHI' },
  // System configuration
  { pattern: /config|configuration|infrastructure/i, level: 'CUI', category: 'SYSTEM' },
]

/**
 * Classify data automatically based on content
 */
export function classifyData(content: string, metadata?: Record<string, any>): ClassificationLevel {
  // Check metadata first
  if (metadata?.classification) {
    return metadata.classification as ClassificationLevel
  }

  // Apply classification rules
  for (const rule of CLASSIFICATION_RULES) {
    if (rule.pattern.test(content)) {
      return rule.level
    }
  }

  // Default to UNCLASSIFIED
  return 'UNCLASSIFIED'
}

/**
 * Get classification level for a resource
 */
export async function getResourceClassification(
  resourceType: string,
  resourceId: string
): Promise<ClassificationLevel> {
  const db = getDb()
  
  const result = await db.query(
    `SELECT classification_level 
     FROM resource_classifications 
     WHERE resource_type = $1 AND resource_id = $2`,
    [resourceType, resourceId]
  )

  if (result.rows.length > 0) {
    return result.rows[0].classification_level
  }

  // Default classification
  return 'UNCLASSIFIED'
}

/**
 * Set classification for a resource
 */
export async function setResourceClassification(
  resourceType: string,
  resourceId: string,
  level: ClassificationLevel,
  category?: string,
  markings?: string[],
  handlingInstructions?: string[]
): Promise<void> {
  const db = getDb()
  
  await db.query(
    `INSERT INTO resource_classifications 
     (resource_type, resource_id, classification_level, category, markings, handling_instructions, created_at, updated_at)
     VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
     ON CONFLICT (resource_type, resource_id) DO UPDATE
     SET classification_level = $3, category = $4, markings = $5, 
         handling_instructions = $6, updated_at = NOW()`,
    [resourceType, resourceId, level, category, JSON.stringify(markings || []), JSON.stringify(handlingInstructions || [])]
  )

  logger.info('Resource classification set', { resourceType, resourceId, level })
}

/**
 * Generate data markings for a classification level
 */
export function generateMarkings(level: ClassificationLevel, category?: string): string[] {
  const markings: string[] = []

  switch (level) {
    case 'TOP_SECRET':
      markings.push('TOP SECRET')
      break
    case 'SECRET':
      markings.push('SECRET')
      break
    case 'CONFIDENTIAL':
      markings.push('CONFIDENTIAL')
      break
    case 'CUI':
      markings.push('CUI')
      if (category) {
        markings.push(`CUI//${category}`)
      }
      break
    case 'UNCLASSIFIED':
      markings.push('UNCLASSIFIED')
      break
  }

  return markings
}

/**
 * Get handling instructions for a classification level
 */
export function getHandlingInstructions(level: ClassificationLevel): string[] {
  const instructions: string[] = []

  switch (level) {
    case 'TOP_SECRET':
      instructions.push('TOP SECRET - Handle as TOP SECRET')
      instructions.push('Authorized personnel only')
      instructions.push('Secure storage required')
      break
    case 'SECRET':
      instructions.push('SECRET - Handle as SECRET')
      instructions.push('Authorized personnel only')
      break
    case 'CONFIDENTIAL':
      instructions.push('CONFIDENTIAL - Handle as CONFIDENTIAL')
      break
    case 'CUI':
      instructions.push('CUI - Controlled Unclassified Information')
      instructions.push('Handle in accordance with CUI requirements')
      break
    case 'UNCLASSIFIED':
      // No special handling required
      break
  }

  return instructions
}

