import type { Prisma } from "@prisma/client";

type DiffRecord = Record<string, unknown>;

function sanitize(value: unknown): Prisma.InputJsonValue {
  if (value === null || value === undefined) return null as unknown as Prisma.InputJsonValue;
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return value;
  }
  if (typeof value === "bigint") {
    return value.toString();
  }
  if (value instanceof Date) {
    return value.toISOString();
  }
  if (Array.isArray(value)) {
    return value.map((item) => sanitize(item));
  }
  if (typeof value === "object") {
    return Object.fromEntries(
      Object.entries(value as Record<string, unknown>).map(([key, nested]) => [key, sanitize(nested)])
    );
  }
  return String(value);
}

export function buildAuditChangeMetadata(before: DiffRecord, after: DiffRecord) {
  const changedFields: string[] = [];
  const beforeChanges: Record<string, Prisma.InputJsonValue> = {};
  const afterChanges: Record<string, Prisma.InputJsonValue> = {};

  for (const key of Object.keys(after)) {
    const beforeValue = sanitize(before[key]);
    const afterValue = sanitize(after[key]);

    if (JSON.stringify(beforeValue) === JSON.stringify(afterValue)) {
      continue;
    }

    changedFields.push(key);
    beforeChanges[key] = beforeValue;
    afterChanges[key] = afterValue;
  }

  return {
    changed_fields: changedFields,
    before: beforeChanges,
    after: afterChanges
  } satisfies Prisma.InputJsonObject;
}
