import React from 'react';
import Markdoc from '@markdoc/markdoc';
import type { Node } from '@markdoc/markdoc';

import styles from './MarkdocRenderer.module.css';

import { nodes } from '@/lib/markdoc/nodes';
import { tags } from '@/lib/markdoc/tags';

import { collectSideNotes, hasComponents } from '@/lib/markdoc/utils';

import { Column } from '@/components/Content/Grid/Column';
import { Row } from '@/components/Content/Grid/Row';
import Sidenote from '@/components/Content/Sidenote/Item';
import SidenoteContainer from '@/components/Content/Sidenote/Container';

interface MarkdocRendererProps {
  content: () => Promise<{ node: Node }>;
  className?: string;
}

const MARGIN_COMPONENTS = ['Sidenote'];

export default async function MarkdocRenderer({
  content,
  className,
}: MarkdocRendererProps) {
  const components = {
    Column,
    Row,
    Sidenote,
  };

  const { node } = await content();
  const errors = Markdoc.validate(node, { tags, nodes });

  if (errors.length) {
    console.error('Markdoc validation errors:', errors);
    throw new Error('Invalid Content');
  }

  const renderable = Markdoc.transform(node, { tags, nodes });
  const sidenotes = collectSideNotes(renderable);
  const showMargin = hasComponents(renderable, MARGIN_COMPONENTS);

  return (
    <div
      className={`${styles.wrapper} ${className} ${showMargin ? styles.hasMargin : ''}`}
    >
      <div className={`${styles.content} content`}>
        {Markdoc.renderers.react(renderable, React, { components })}
      </div>
      <SidenoteContainer items={sidenotes} />
    </div>
  );
}
