import { Article } from '@/features/posts/_lib/transformers';
import renderInline from './inline-renderer';
import { createElement } from 'react';
import WidgetRenderer from './widget-renderer';
import { ImageAlign, ImageFloat, NodeType } from '@/config/enums/tip-tap';
import type { JSONContent } from '@tiptap/react';
import { getTextAlignClass } from './renderer-helpers';
import { cn } from '@/lib/utils';
import Image from 'next/image';
import { ImageQuality } from '@/config/enums/image-quality';

export default function TiptapNodeRenderer({
  node,
  post
}: {
  node: JSONContent;
  post?: Article;
}) {
  const align = getTextAlignClass(node);

  switch (node.type) {
    case NodeType.PARAGRAPH:
      return <p className={align}>{renderInline(node.content)}</p>;

    case NodeType.HEADING:
      return createElement(
        `h${node.attrs?.level ?? 2}`,
        {
          className: align
        },
        renderInline(node.content)
      );

    case NodeType.BLOCKQUOTE:
      return (
        <blockquote className='my-6 border-l-4 border-neutral-300 pl-4 text-neutral-700 italic'>
          {node.content?.map(renderBlock)}
        </blockquote>
      );

    case NodeType.BULLET_LIST:
      return (
        <ul className="my-6 ml-10 table space-y-2 [&>li]:marker:text-sm [&>li]:marker:content-[url('/icons/icon_arrow_right_sm.svg')_'__']">
          {node.content?.map(renderBlock)}
        </ul>
      );

    case NodeType.ORDERED_LIST:
      return (
        <ol className='my-6 ml-10 table list-decimal space-y-2'>
          {node.content?.map(renderBlock)}
        </ol>
      );

    case NodeType.LIST_ITEM:
      return <li>{node.content?.map(renderBlock)}</li>;

    case NodeType.HORIZONTAL_RULE:
      return <hr className='my-8 border-neutral-300' />;

    case NodeType.TABLE: {
      const firstRow = node.content?.[0];
      const tableWidth = 640;
      return (
        <div className='my-6 overflow-x-auto'>
          <table className='w-full min-w-120 table-fixed border-collapse text-sm'>
            {firstRow && (
              <colgroup>
                {firstRow.content?.map((cell, index) => {
                  const colWidthPx = cell.attrs?.colwidth?.[0];

                  const widthPercent =
                    colWidthPx && tableWidth
                      ? `${(colWidthPx / tableWidth) * 100}%`
                      : undefined;

                  return (
                    <col
                      key={index}
                      style={widthPercent ? { width: widthPercent } : undefined}
                    />
                  );
                })}
              </colgroup>
            )}

            <tbody>{node.content?.map(renderBlock)}</tbody>
          </table>
        </div>
      );
    }

    case NodeType.TABLE_ROW:
      return <tr>{node.content?.map(renderBlock)}</tr>;

    case NodeType.TABLE_HEADER:
      return (
        <th
          className={cn(
            'min-w-60 border bg-neutral-100 px-3 py-2 font-semibold',
            align
          )}
        >
          {node.content?.map(renderBlock)}
        </th>
      );

    case NodeType.TABLE_CELL:
      return (
        <td className={cn('min-w-60 border px-3 py-2 align-top', align)}>
          {node.content?.map(renderBlock)}
        </td>
      );

    case NodeType.IMAGE:
      const {
        src,
        alt,
        width,
        height,
        align: imageAlign,
        float
      } = node.attrs ?? {};

      return (
        <div className='grid'>
          <Image
            quality={ImageQuality.MEDIUM}
            src={src}
            alt={alt || 'artikelbillede'}
            width={width ?? 1000}
            height={height ?? 600}
            className={cn(
              'my-4 max-w-full',
              imageAlign === ImageAlign.LEFT && 'mr-auto',
              imageAlign === ImageAlign.CENTER && 'mx-auto',
              imageAlign === ImageAlign.RIGHT && 'ml-auto',
              float === ImageFloat.LEFT && 'lg:float-left lg:mr-4',
              float === ImageFloat.RIGHT && 'lg:float-right lg:ml-4'
            )}
          />
        </div>
      );

    case NodeType.IFRAME:
      const iframeWidth = Number(node.attrs?.width) || 560;
      const iframeHeight = Number(node.attrs?.height) || 315;
      const iframeRatio = (iframeHeight / iframeWidth) * 100; //
      return (
        <div
          className='relative my-6 w-full'
          style={{
            paddingTop: `${iframeRatio}%`
          }}
        >
          <iframe
            {...node.attrs}
            className='absolute top-0 left-0 size-full w-full border-0'
          />
        </div>
      );

    case NodeType.WIDGET_BLOCK:
      return <WidgetRenderer node={node} post={post} />;

    default:
      return null;
  }
}

function renderBlock(node: JSONContent, index: number) {
  return <TiptapNodeRenderer key={index} node={node} />;
}
