/**
 * Redaction Utilities
 *
 * Provides utilities to redact sensitive data from logs to prevent PII leakage.
 */

/**
 * Sensitive field names that should be redacted
 */
const SENSITIVE_FIELDS = new Set([
  "privateKey",
  "token",
  "oidcToken",
  "accessToken",
  "refreshToken",
  "password",
  "secret",
  "apiKey",
  "metadata",
  "payload",
  "signature",
]);

/**
 * Redact a user ID to prevent PII leakage
 * @param _userId - User ID to redact
 * @returns Redacted user ID
 */
export function redactUserId(_userId: string | null | undefined): string {
  return "user-***";
}

/**
 * Redact an instance ID to prevent system information leakage
 * @param _instanceId - Instance ID to redact
 * @returns Redacted instance ID
 */
export function redactInstanceId(_instanceId: string | null | undefined): string {
  return "instance-***";
}

/**
 * Recursively redact sensitive data from an object
 * @param data - Data to redact
 * @returns Redacted data (creates a new object/array)
 */
export function redactSensitiveData<T>(data: T): T {
  // Handle primitives and null/undefined
  if (data === null || data === undefined) {
    return data;
  }

  if (typeof data !== "object") {
    return data;
  }

  // Handle arrays
  if (Array.isArray(data)) {
    const result = data.map((item: unknown) => redactSensitiveData(item));
    return result as unknown as T;
  }

  // Handle objects
  const redacted: Record<string, unknown> = {};

  for (const [key, value] of Object.entries(data)) {
    // Redact sensitive fields
    if (SENSITIVE_FIELDS.has(key)) {
      redacted[key] = "[REDACTED]";
      continue;
    }

    // Redact user IDs
    if (key === "userId" || key === "remoteUserId" || key === "localUserId") {
      redacted[key] = redactUserId(value as string);
      continue;
    }

    // Redact instance IDs
    if (key === "instanceId" || key === "remoteInstanceId") {
      redacted[key] = redactInstanceId(value as string);
      continue;
    }

    // Redact id field within user/instance context
    if (key === "id" && typeof value === "string") {
      // Check if this might be a user or instance ID based on value format
      if (value.startsWith("user-") || value.startsWith("instance-")) {
        if (value.startsWith("user-")) {
          redacted[key] = redactUserId(value);
        } else {
          redacted[key] = redactInstanceId(value);
        }
        continue;
      }
    }

    // Recursively redact nested objects/arrays
    if (typeof value === "object" && value !== null) {
      redacted[key] = redactSensitiveData(value);
    } else {
      redacted[key] = value;
    }
  }

  return redacted as T;
}
