/**
 * Content Serializer
 *
 * Converts Tiptap JSON page tree into markdown for agent prompts.
 * Uses @tiptap/markdown's MarkdownManager for standard node serialization,
 * with custom handling only for pageLink nodes.
 */

import { Node, type JSONContent } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
import Link from '@tiptap/extension-link';
import { MarkdownManager } from '@tiptap/markdown';

/**
 * Minimal page shape needed for serialization.
 */
export interface PageForSerialization {
  id: string;
  parentPageId: string | null;
  title: string;
  content: string | null; // JSON string from Tiptap
  sortOrder: number;
}

/**
 * Server-side pageLink node — only needs schema definition + markdown rendering.
 */
const ServerPageLink = Node.create({
  name: 'pageLink',
  group: 'block',
  atom: true,

  addAttributes() {
    return {
      pageId: { default: null },
    };
  },

  renderMarkdown(node: JSONContent) {
    const pageId = (node.attrs?.pageId as string) ?? '';
    return `[[page:${pageId}]]\n\n`;
  },
});

let _manager: MarkdownManager | null = null;

function getManager(): MarkdownManager {
  if (!_manager) {
    _manager = new MarkdownManager({
      extensions: [StarterKit, Link, ServerPageLink],
    });
  }
  return _manager;
}

/**
 * Convert a Tiptap JSON document to markdown.
 */
export function tiptapJsonToMarkdown(json: unknown): string {
  if (!json || typeof json !== 'object') return '';

  const doc = json as JSONContent;
  if (doc.type !== 'doc' || !Array.isArray(doc.content)) return '';

  return getManager().serialize(doc).trim();
}

/**
 * Serialize an array of pages into a single markdown document.
 * Pages are organized as a tree (root first, then children by sortOrder).
 *
 * Each page is marked with <!-- page:$id --> so the agent can reference them.
 */
export function serializePageTree(pages: PageForSerialization[]): string {
  if (pages.length === 0) return '';

  // Build parent→children map
  const childrenMap = new Map<string | null, PageForSerialization[]>();
  for (const page of pages) {
    const parentKey = page.parentPageId;
    if (!childrenMap.has(parentKey)) {
      childrenMap.set(parentKey, []);
    }
    childrenMap.get(parentKey)!.push(page);
  }

  // Sort children by sortOrder
  for (const children of childrenMap.values()) {
    children.sort((a, b) => a.sortOrder - b.sortOrder);
  }

  // Render tree depth-first
  const sections: string[] = [];

  function renderPage(page: PageForSerialization, depth: number): void {
    const headerPrefix = '#'.repeat(Math.min(depth + 1, 6));
    let section = `<!-- page:${page.id} -->\n${headerPrefix} ${page.title}`;

    if (page.content) {
      try {
        const parsed = JSON.parse(page.content);
        const md = tiptapJsonToMarkdown(parsed);
        if (md.trim()) {
          section += `\n\n${md}`;
        }
      } catch {
        // Invalid JSON — skip content
      }
    }

    sections.push(section);

    const children = childrenMap.get(page.id) ?? [];
    for (const child of children) {
      renderPage(child, depth + 1);
    }
  }

  // Start from root pages (parentPageId is null)
  const roots = childrenMap.get(null) ?? [];
  for (const root of roots) {
    renderPage(root, 1);
  }

  return sections.join('\n\n');
}
