import { defaultJSXConverters, RichText } from '@payloadcms/richtext-lexical/react';
import type { JSXConverters } from '@payloadcms/richtext-lexical/react';
import Image from 'next/image';

// Import all custom React components that were previously mapped via MDX
import StickyNarrative from '@/components/blog/StickyNarrative';
import ComparisonGrid from '@/components/blog/ComparisonGrid';
import VisualLinkPreview from '@/components/blog/VisualLinkPreview';
import TechnicalGrid from '@/components/blog/TechnicalGrid';
import HighlightBox from '@/components/blog/HighlightBox';
import AnimatedImage from '@/components/blog/AnimatedImage';
import ChatBubble from '@/components/blog/ChatBubble';
import PowerCTA from '@/components/blog/PowerCTA';
import { Callout } from '@/components/ui/Callout';
import Stats from '@/components/blog/Stats';
import SplitHeading from '@/components/blog/SplitHeading';
import ProductTabs from '@/components/ProductTabs';
import ProductTechnicalData from '@/components/ProductTechnicalData';

const jsxConverters: JSXConverters = {
  ...defaultJSXConverters,
  // Let the default converters handle text nodes to preserve valid formatting
  // If the text node contains raw HTML (from messy migrations), render it as HTML instead of escaping it
  text: ({ node }: any) => {
    const text = node.text;
    // Handle markdown-style lists embedded in text nodes from MDX migration
    if (text && text.includes('\n- ')) {
      const parts = text.split('\n- ').filter((p: string) => p.trim() !== '');
      // If first part doesn't start with "- ", it's a prefix paragraph
      const startsWithDash = text.trimStart().startsWith('- ');
      const prefix = startsWithDash ? null : parts.shift();
      return (
        <>
          {prefix && (
            <span dangerouslySetInnerHTML={prefix.includes('<') ? { __html: prefix } : undefined}>
              {!prefix.includes('<') ? prefix : undefined}
            </span>
          )}
          <ul className="list-disc pl-6 my-4 space-y-2">
            {parts.map((item: string, i: number) => {
              const cleanItem = item.trim();
              if (cleanItem.includes('<')) {
                return <li key={i} dangerouslySetInnerHTML={{ __html: cleanItem }} />;
              }
              return <li key={i}>{cleanItem}</li>;
            })}
          </ul>
        </>
      );
    }

    if (text && (text.includes('<') || text.includes('data-start'))) {
      return <span dangerouslySetInnerHTML={{ __html: text }} />;
    }

    // Handle markdown-style links [text](url) from MDX migration
    if (text && /\[([^\]]+)\]\(([^)]+)\)/.test(text)) {
      const parts: React.ReactNode[] = [];
      const remaining = text;
      let key = 0;
      const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
      let match;
      let lastIndex = 0;
      while ((match = linkRegex.exec(remaining)) !== null) {
        if (match.index > lastIndex) {
          parts.push(<span key={key++}>{remaining.slice(lastIndex, match.index)}</span>);
        }
        parts.push(
          <a
            key={key++}
            href={match[2]}
            target="_blank"
            rel="noopener noreferrer"
            className="text-primary underline decoration-primary/30 hover:decoration-primary transition-colors"
          >
            {match[1]}
          </a>,
        );
        lastIndex = match.index + match[0].length;
      }
      if (lastIndex < remaining.length) {
        parts.push(<span key={key++}>{remaining.slice(lastIndex)}</span>);
      }
      return <>{parts}</>;
    }

    // Handle newlines in text nodes — convert to <br> for proper line breaks
    if (text && text.includes('\n')) {
      const lines = text.split('\n');
      return (
        <>
          {lines.map((line: string, i: number) => (
            <span key={i}>
              {line}
              {i < lines.length - 1 && <br />}
            </span>
          ))}
        </>
      );
    }

    if (node.format === 1) return <strong>{text}</strong>;
    if (node.format === 2) return <em>{text}</em>;
    return <span>{text}</span>;
  },
  // Scale headings to prevent multiple H1s (H1 -> H2, etc)
  h1: ({ children }: any) => <h2 className="text-3xl md:text-4xl font-bold my-6">{children}</h2>,
  h2: ({ children }: any) => <h3 className="text-2xl md:text-3xl font-bold my-5">{children}</h3>,
  h3: ({ children }: any) => <h4 className="text-xl md:text-2xl font-bold my-4">{children}</h4>,

  blocks: {
    // ... preserved existing blocks ...
    // Map the custom Payload Blocks created in src/payload/blocks to their React components
    // Payload Lexical exposes blocks using the 'block-[slug]' pattern
    stickyNarrative: ({ node }: any) => (
      <StickyNarrative title={node.fields.title} items={node.fields.items} />
    ),
    'block-stickyNarrative': ({ node }: any) => (
      <StickyNarrative title={node.fields.title} items={node.fields.items} />
    ),
    comparisonGrid: ({ node }: any) => (
      <ComparisonGrid
        title={node.fields.title}
        leftLabel={node.fields.leftLabel}
        rightLabel={node.fields.rightLabel}
        items={node.fields.items}
      />
    ),
    'block-comparisonGrid': ({ node }: any) => (
      <ComparisonGrid
        title={node.fields.title}
        leftLabel={node.fields.leftLabel}
        rightLabel={node.fields.rightLabel}
        items={node.fields.items}
      />
    ),
    visualLinkPreview: ({ node }: any) => (
      <VisualLinkPreview
        url={node.fields.url}
        title={node.fields.title}
        summary={node.fields.summary}
        image={node.fields.image?.sizes?.card?.url || node.fields.image?.url}
      />
    ),
    'block-visualLinkPreview': ({ node }: any) => (
      <VisualLinkPreview
        url={node.fields.url}
        title={node.fields.title}
        summary={node.fields.summary}
        image={node.fields.image?.sizes?.card?.url || node.fields.image?.url}
      />
    ),
    technicalGrid: ({ node }: any) => (
      <TechnicalGrid title={node.fields.title} items={node.fields.items} />
    ),
    'block-technicalGrid': ({ node }: any) => {
      console.log('[PayloadRichText] Rendering block-technicalGrid:', node.fields.title);
      return <TechnicalGrid title={node.fields.title} items={node.fields.items} />;
    },
    highlightBox: ({ node }: any) => (
      <HighlightBox title={node.fields.title} color={node.fields.color}>
        <RichText data={node.fields.content} converters={jsxConverters} />
      </HighlightBox>
    ),
    'block-highlightBox': ({ node }: any) => (
      <HighlightBox title={node.fields.title} color={node.fields.color}>
        <RichText data={node.fields.content} converters={jsxConverters} />
      </HighlightBox>
    ),
    animatedImage: ({ node }: any) => (
      <AnimatedImage
        src={node.fields.src}
        alt={node.fields.alt}
        width={node.fields.width}
        height={node.fields.height}
      />
    ),
    'block-animatedImage': ({ node }: any) => (
      <AnimatedImage
        src={node.fields.src}
        alt={node.fields.alt}
        width={node.fields.width}
        height={node.fields.height}
      />
    ),
    chatBubble: ({ node }: any) => (
      <ChatBubble
        author={node.fields.author}
        avatar={node.fields.avatar}
        role={node.fields.role}
        align={node.fields.align}
      >
        <RichText data={node.fields.content} converters={jsxConverters} />
      </ChatBubble>
    ),
    'block-chatBubble': ({ node }: any) => (
      <ChatBubble
        author={node.fields.author}
        avatar={node.fields.avatar}
        role={node.fields.role}
        align={node.fields.align}
      >
        <RichText data={node.fields.content} converters={jsxConverters} />
      </ChatBubble>
    ),
    powerCTA: ({ node }: any) => <PowerCTA locale={node.fields.locale} />,
    'block-powerCTA': ({ node }: any) => <PowerCTA locale={node.fields.locale} />,
    callout: ({ node }: any) => (
      <Callout type={node.fields.type} title={node.fields.title}>
        <RichText data={node.fields.content} converters={jsxConverters} />
      </Callout>
    ),
    'block-callout': ({ node }: any) => (
      <Callout type={node.fields.type} title={node.fields.title}>
        <RichText data={node.fields.content} converters={jsxConverters} />
      </Callout>
    ),
    stats: ({ node }: any) => <Stats stats={node.fields.stats} />,
    'block-stats': ({ node }: any) => <Stats stats={node.fields.stats} />,
    splitHeading: ({ node }: any) => (
      <SplitHeading id={node.fields.id} level={node.fields.level}>
        {node.fields.title}
      </SplitHeading>
    ),
    'block-splitHeading': ({ node }: any) => (
      <SplitHeading id={node.fields.id} level={node.fields.level}>
        {node.fields.title}
      </SplitHeading>
    ),
    productTabs: ({ node }: any) => (
      <ProductTabs
        technicalData={
          <ProductTechnicalData
            data={{
              technicalItems: node.fields.technicalItems,
              voltageTables: node.fields.voltageTables,
            }}
          />
        }
      >
        <></>
      </ProductTabs>
    ),
    'block-productTabs': ({ node }: any) => (
      <ProductTabs
        technicalData={
          <ProductTechnicalData
            data={{
              technicalItems: node.fields.technicalItems,
              voltageTables: node.fields.voltageTables,
            }}
          />
        }
      >
        {node.fields.content && <RichText data={node.fields.content} converters={jsxConverters} />}
      </ProductTabs>
    ),
  },
  // Custom converter for the Payload "upload" Lexical node (Media collection)
  // This natively reconstructs Next.js <Image /> tags pointing to the focal-point cropped sizes
  upload: ({ node }: any) => {
    // Attempt to extract the highly optimized 'card' generated size from Payload, fallback to raw url
    let src = node?.value?.sizes?.card?.url || node?.value?.url;
    const alt = node?.value?.alt || 'Blog Post Media';

    if (!src) return null;

    // Strip legacy imgproxy query parameters (e.g. ?ar=16:9) that crash Next.js 14+ localPatterns
    if (src.includes('?')) {
      src = src.split('?')[0];
    }

    // Fallback dimensions if unmapped or loading from raw
    const width = node?.value?.sizes?.card?.width || 800;
    const height = node?.value?.sizes?.card?.height || 600;

    return (
      <figure className="my-8 md:my-12 relative w-full rounded-2xl md:rounded-[32px] overflow-hidden shadow-xl md:shadow-2xl">
        <Image
          src={src}
          alt={alt}
          width={width}
          height={height}
          className="w-full object-cover transition-transform duration-700 hover:scale-105"
          sizes="(max-width: 768px) 100vw, (max-width: 1200px) 75vw, 60vw"
          style={{
            objectPosition: `${node?.value?.focalX ?? 50}% ${node?.value?.focalY ?? 50}%`,
          }}
        />
        {node?.value?.caption && (
          <figcaption className="p-4 bg-neutral-dark text-white/80 text-sm text-center italic border-t border-white/10">
            {node.value.caption}
          </figcaption>
        )}
      </figure>
    );
  },
};

export default function PayloadRichText({ data }: { data: any }) {
  if (!data) return null;

  return (
    <div className="article-content max-w-none">
      <RichText data={data} converters={jsxConverters} />
    </div>
  );
}
