export type ActorType = 'user' | 'service' | 'system' | 'operator';

export type AuditEvent = {
  audit_event_id: string;
  timestamp: string;
  actor_type: ActorType;
  actor_id: string;
  tenant_id: string;
  entity_id: string;
  action: string;
  resource_type: string;
  resource_id: string;
  correlation_id?: string;
  request_id?: string;
  before_hash?: string;
  after_hash?: string;
  decision?: string;
  reason_code?: string;
  metadata_redacted: Record<string, unknown>;
};

const SENSITIVE_KEY_PATTERNS = [
  /password/i,
  /secret/i,
  /token/i,
  /api[_-]?key/i,
  /private[_-]?key/i,
  /credential/i,
  /ssn/i,
  /iban/i,
  /email/i,
  /phone/i,
  /address/i,
];

const REDACTED = '[REDACTED]';

function isSensitiveKey(key: string): boolean {
  return SENSITIVE_KEY_PATTERNS.some((p) => p.test(key));
}

export function redactMetadata(
  metadata: Record<string, unknown>
): Record<string, unknown> {
  const out: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(metadata)) {
    if (isSensitiveKey(key)) {
      out[key] = REDACTED;
      continue;
    }
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      out[key] = redactMetadata(value as Record<string, unknown>);
    } else {
      out[key] = value;
    }
  }
  return out;
}

export function createAuditEvent(
  partial: Omit<AuditEvent, 'metadata_redacted' | 'timestamp'> & {
    metadata?: Record<string, unknown>;
  }
): AuditEvent {
  const { metadata, ...rest } = partial;
  return {
    ...rest,
    timestamp: new Date().toISOString(),
    metadata_redacted: redactMetadata(metadata ?? {}),
  };
}
