import { defaultJSXConverters, RichText } from '@payloadcms/richtext-lexical/react';
import type { JSXConverters } from '@payloadcms/richtext-lexical/react';
import Image from 'next/image';
import { Fragment } from 'react';
import { allBlocks } from '@/src/payload/blocks/allBlocks';
import ObfuscatedEmail from '@/components/ObfuscatedEmail';
import ObfuscatedPhone from '@/components/ObfuscatedPhone';

/**
 * Splits a text string on \n and intersperses <br /> elements.
 */
function textWithLineBreaks(text: string, key: string) {
  const parts = text.split('\n');
  if (parts.length === 1) return text;
  return parts.map((part, i) => (
    <Fragment key={`${key}-${i}`}>
      {part}
      {i < parts.length - 1 && <br />}
    </Fragment>
  ));
}

const jsxConverters: JSXConverters = {
  ...defaultJSXConverters,
  linebreak: () => <br />,
  text: ({ node }: any) => {
    let content: React.ReactNode = node.text || '';
    if (typeof content === 'string' && content.includes('\n')) {
      content = textWithLineBreaks(content, `t-${(node.text || '').slice(0, 8)}`);
    }

    if (typeof content === 'string' && content.includes('@')) {
      const emailRegex = /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g;
      const parts = content.split(emailRegex);
      content = parts.map((part, i) => {
        if (part.match(emailRegex)) {
          return <ObfuscatedEmail key={`e-${i}`} email={part} />;
        }
        return part;
      });
    }

    if (typeof content === 'string' && content.match(/\+\d+/)) {
      const phoneRegex = /(\+\d{1,4}[\d\s-]{5,15})/g;
      const parts = content.split(phoneRegex);
      content = parts.map((part, i) => {
        if (part.match(phoneRegex)) {
          return <ObfuscatedPhone key={`p-${i}`} phone={part} />;
        }
        return part;
      });
    }

    return content;
  },
  upload: ({ node }: any) => {
    return (
      <div className="relative w-full aspect-video my-8 rounded-3xl overflow-hidden shadow-2xl group">
        <Image
          src={node.value.url}
          alt={node.value.alt || ''}
          fill
          sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
          className="object-cover transition-transform duration-700 group-hover:scale-105"
        />
      </div>
    );
  },
  blocks: allBlocks.reduce((acc, block) => {
    const Component = block.render;
    if (!Component) return acc;

    const renderFn = ({ node }: any) => {
      // Pass all fields as props to the component, and also as 'data' prop
      return <Component {...node.fields} data={node.fields} />;
    };

    // Map both the direct slug and the block- prefixed slug
    return {
      ...acc,
      [block.slug]: renderFn,
      [`block-${block.slug}`]: renderFn,
    };
  }, {}),
};

export default function PayloadRichText({ data, className, references }: { data: any; className?: string; references?: any[] }) {
  if (!data) return null;
  return (
    <div className={className}>
      <RichText data={data} converters={jsxConverters} />
    </div>
  );
}
