import type { Json } from "@/types/supabase";
import {
  editorBlockDocumentFromContent,
  editorBlockDocumentFromTiptapDoc,
  legacyBlocksFromEditorBlockDocument,
  normalizeEditorBlockDocument,
  type EditorBlockDocument,
  type TiptapDoc,
} from "@/lib/documents/tiptap-content-converter";

export type DocumentSavePayload = {
  documentId: string;
  workspaceId: string | null;
  revision: number | null;
  editorDocument: EditorBlockDocument;
  content: Json;
  tiptapDocument: TiptapDoc | null;
  conflictDetectionKey: string | null;
  snapshotCapturedAt: string | null;
  blockCount: number | null;
};

type BuildDocumentSavePayloadInput = {
  documentId: string;
  workspaceId?: string | null;
  revision?: number | null;
  editorDocument?: unknown;
  content?: Json;
  tiptapDocument?: unknown;
  conflictDetectionKey?: string | null;
  snapshotCapturedAt?: string | null;
  blockCount?: number | null;
};

function resolveEditorDocument(
  input: BuildDocumentSavePayloadInput,
  normalizedDocumentId: string,
): EditorBlockDocument {
  if (input.editorDocument != null) {
    return normalizeEditorBlockDocument(input.editorDocument, normalizedDocumentId);
  }
  if (typeof input.content !== "undefined") {
    return normalizeEditorBlockDocument(
      editorBlockDocumentFromContent(input.content),
      normalizedDocumentId,
    );
  }
  if (input.tiptapDocument != null) {
    return normalizeEditorBlockDocument(
      editorBlockDocumentFromTiptapDoc(input.tiptapDocument, normalizedDocumentId),
      normalizedDocumentId,
    );
  }
  return normalizeEditorBlockDocument(
    {
      documentId: normalizedDocumentId,
      rootBlockIds: [],
      blocks: [],
    },
    normalizedDocumentId,
  );
}

export function buildDocumentSavePayload(
  input: BuildDocumentSavePayloadInput,
): DocumentSavePayload {
  const documentId = input.documentId.trim();
  const editorDocument = resolveEditorDocument(input, documentId);
  const shouldDeriveLegacyContent =
    input.editorDocument != null ||
    input.tiptapDocument != null ||
    typeof input.content === "undefined";
  const content: Json = shouldDeriveLegacyContent
    ? (legacyBlocksFromEditorBlockDocument(editorDocument) as Json)
    : (input.content as Json);
  const revision =
    typeof input.revision === "number" && Number.isInteger(input.revision) && input.revision >= 0
      ? input.revision
      : null;
  const conflictDetectionKey =
    typeof input.conflictDetectionKey === "string" && input.conflictDetectionKey.trim()
      ? input.conflictDetectionKey.trim()
      : null;
  const snapshotCapturedAt =
    typeof input.snapshotCapturedAt === "string" && input.snapshotCapturedAt.trim()
      ? input.snapshotCapturedAt.trim()
      : null;
  const blockCount =
    typeof input.blockCount === "number" && Number.isInteger(input.blockCount) && input.blockCount >= 0
      ? input.blockCount
      : null;
  const tiptapDocument =
    input.tiptapDocument && typeof input.tiptapDocument === "object"
      ? (input.tiptapDocument as TiptapDoc)
      : null;

  return {
    documentId,
    workspaceId: input.workspaceId?.trim() || null,
    revision,
    editorDocument,
    content,
    tiptapDocument,
    conflictDetectionKey,
    snapshotCapturedAt,
    blockCount,
  };
}
