import CryptoJS from 'crypto-js'
import { randomBytes } from 'crypto'
import dotenv from 'dotenv'

// Load environment variables
dotenv.config()

// Generate a secure encryption key from environment or create a new one
const getEncryptionKey = (): string => {
  let key = process.env.FIELD_ENCRYPTION_KEY
  
  if (!key) {
    // Use the default development key
    key = 'dev_field_key_change_in_production_32chars_min!'
    console.warn('⚠️ No FIELD_ENCRYPTION_KEY found. Using default development key.')
    console.warn('⚠️ Set FIELD_ENCRYPTION_KEY in your .env file for production!')
  }
  
  return key
}

const ENCRYPTION_KEY = getEncryptionKey()

export class FieldEncryption {
  /**
   * Encrypt sensitive field data
   */
  static encrypt(text: string | null | undefined): string | null {
    if (!text) return null
    
    try {
      const encrypted = CryptoJS.AES.encrypt(text, ENCRYPTION_KEY).toString()
      return encrypted
    } catch (error) {
      console.error('Encryption error:', error)
      throw new Error('Failed to encrypt data')
    }
  }

  /**
   * Decrypt sensitive field data
   */
  static decrypt(encryptedText: string | null | undefined): string | null {
    if (!encryptedText) return null
    
    try {
      const decrypted = CryptoJS.AES.decrypt(encryptedText, ENCRYPTION_KEY)
      return decrypted.toString(CryptoJS.enc.Utf8)
    } catch (error) {
      console.error('Decryption error:', error)
      throw new Error('Failed to decrypt data')
    }
  }

  /**
   * Encrypt multiple fields in an object
   */
  static encryptFields<T extends Record<string, any>>(
    obj: T,
    fields: (keyof T)[]
  ): T {
    const encrypted = { ...obj }
    
    for (const field of fields) {
      if (encrypted[field]) {
        encrypted[field] = this.encrypt(encrypted[field] as string) as any
      }
    }
    
    return encrypted
  }

  /**
   * Decrypt multiple fields in an object
   */
  static decryptFields<T extends Record<string, any>>(
    obj: T,
    fields: (keyof T)[]
  ): T {
    const decrypted = { ...obj }
    
    for (const field of fields) {
      if (decrypted[field]) {
        decrypted[field] = this.decrypt(decrypted[field] as string) as any
      }
    }
    
    return decrypted
  }

  /**
   * Hash data for searching (one-way)
   */
  static hash(text: string): string {
    return CryptoJS.SHA256(text.toLowerCase()).toString()
  }
}

// List of sensitive fields that should be encrypted
export const SENSITIVE_EMPLOYEE_FIELDS = [
  'email',
  'phone',
  'mobile',
  'clearance_level',
  'clearance_valid_until'
]

export const SENSITIVE_USER_FIELDS = [
  'email'
]