import { encryptData } from './encrypt.js';

/**
 * Utility-Funktionen zum Sanitizing von Log-Daten
 * Entfernt oder verschlüsselt personenbezogene Daten aus Request/Response-Bodies
 */

// Felder, die personenbezogene Daten enthalten können
const SENSITIVE_FIELDS = [
  'password',
  'passwort',
  'email',
  'eMail',
  'e-mail',
  'phone',
  'telefon',
  'telephone',
  'firstName',
  'first_name',
  'lastName',
  'last_name',
  'name',
  'street',
  'address',
  'adresse',
  'city',
  'stadt',
  'postalCode',
  'postal_code',
  'plz',
  'birthDate',
  'birth_date',
  'geburtstag',
  'token',
  'accessToken',
  'access_token',
  'refreshToken',
  'refresh_token',
  'cookie',
  'authcode',
  'authCode',
  'session',
  'sessionId',
  'session_id',
  'apiKey',
  'api_key',
  'secret',
  'credentials',
  'creditCard',
  'credit_card',
  'iban',
  'accountNumber',
  'account_number'
];

/**
 * Entfernt oder maskiert personenbezogene Daten aus einem Objekt
 * @param {Object|string} data - Das zu sanitizierende Objekt oder JSON-String
 * @param {boolean} encrypt - Wenn true, werden sensible Felder verschlüsselt statt entfernt
 * @returns {Object|string} - Das sanitizierte Objekt oder JSON-String
 */
export function sanitizeLogData(data, encrypt = false) {
  if (!data) {
    return null;
  }

  // Wenn es ein String ist, versuche es als JSON zu parsen
  let obj;
  let isString = false;
  
  if (typeof data === 'string') {
    isString = true;
    try {
      obj = JSON.parse(data);
    } catch (e) {
      // Wenn es kein JSON ist, kürze den String einfach
      return data.length > 500 ? data.substring(0, 500) + '... (truncated)' : data;
    }
  } else if (typeof data === 'object') {
    obj = data;
  } else {
    return data;
  }

  // Rekursiv durch das Objekt gehen
  const sanitized = sanitizeObject(obj, encrypt);

  // Wenn es ursprünglich ein String war, zurück zu String konvertieren
  if (isString) {
    try {
      return JSON.stringify(sanitized);
    } catch (e) {
      return '[Unable to serialize sanitized data]';
    }
  }

  return sanitized;
}

/**
 * Sanitiziert ein Objekt rekursiv
 */
function sanitizeObject(obj, encrypt = false) {
  if (obj === null || obj === undefined) {
    return obj;
  }

  // Arrays
  if (Array.isArray(obj)) {
    return obj.map(item => sanitizeObject(item, encrypt));
  }

  // Objekte
  if (typeof obj === 'object') {
    const sanitized = {};
    
    for (const [key, value] of Object.entries(obj)) {
      const lowerKey = key.toLowerCase();
      
      // Prüfe, ob das Feld sensibel ist
      const isSensitive = SENSITIVE_FIELDS.some(field => 
        lowerKey.includes(field.toLowerCase())
      );

      if (isSensitive) {
        if (encrypt && value) {
          // Verschlüssele den Wert vollständig
          try {
            const valueStr = typeof value === 'string' ? value : JSON.stringify(value);
            const encrypted = encryptData(valueStr);
            // Speichere vollständig verschlüsselt (kann bei Bedarf entschlüsselt werden)
            sanitized[key] = encrypted;
          } catch (e) {
            // Bei Verschlüsselungsfehler: Maskiere stattdessen
            sanitized[key] = '[REDACTED]';
          }
        } else {
          // Entferne oder maskiere den Wert (ohne Verschlüsselung)
          if (typeof value === 'string' && value.length > 0) {
            // Zeige nur die ersten 2 Zeichen
            sanitized[key] = value.substring(0, 2) + '***[REDACTED]';
          } else {
            sanitized[key] = '[REDACTED]';
          }
        }
      } else if (typeof value === 'object') {
        // Rekursiv für verschachtelte Objekte
        sanitized[key] = sanitizeObject(value, encrypt);
      } else {
        sanitized[key] = value;
      }
    }
    
    return sanitized;
  }

  // Primitive Werte
  return obj;
}

/**
 * Kürzt einen String auf eine maximale Länge
 */
export function truncateString(str, maxLength = 1000) {
  if (!str || typeof str !== 'string') {
    return str;
  }
  
  if (str.length <= maxLength) {
    return str;
  }
  
  return str.substring(0, maxLength) + '... (truncated)';
}

/**
 * Sanitiziert IP-Adressen (kürzt auf ersten 3 Oktetten)
 */
export function sanitizeIpAddress(ip) {
  if (!ip) {
    return null;
  }
  
  // IPv4: 192.168.1.100 -> 192.168.1.xxx
  if (ip.includes('.')) {
    const parts = ip.split('.');
    if (parts.length === 4) {
      return `${parts[0]}.${parts[1]}.${parts[2]}.xxx`;
    }
  }
  
  // IPv6: Kürze auf ersten Teil
  if (ip.includes(':')) {
    const parts = ip.split(':');
    return parts[0] + ':xxx';
  }
  
  return ip;
}

/**
 * Sanitiziert User-Agent-Strings (entfernt spezifische Versionen)
 */
export function sanitizeUserAgent(userAgent) {
  if (!userAgent) {
    return null;
  }
  
  // Entferne spezifische Versionsnummern, behalte nur Browser/OS-Typ
  return userAgent
    .replace(/\d+\.\d+\.\d+\.\d+/g, 'x.x.x.x') // Versionsnummern
    .substring(0, 200); // Kürze auf 200 Zeichen
}

