import { Fragment } from 'react';

import type { TextProps } from '~/src/components/Text';
import type { FC, ReactNode } from 'react';

import Link from '~/src/components/Link2';
import Text from '~/src/components/Text';

interface FormattedTextProps extends Omit<TextProps, 'children'> {
  text: string;
  withLinkify: boolean;
  children?: ReactNode;
}

const FormattedText: FC<FormattedTextProps> = ({
  text,
  withLinkify,
  children,
  ...textProps
}) => {
  return (
    <Text {...textProps} style={{ overflow: 'visible' }} isParagraph>
      {text
        // replace surplus whitespace (max 1 empty line)
        .replace(/\n\n+/g, '\n\n')

        // remove leading whitespace
        .replace(/^\s+/g, '')

        // remove trailing whitespace
        .replace(/\s+$/g, '')

        .split(/\n/g)
        .map((textChunk, index, items) => {
          // const margin = index ? `${Math.round(textSize * 1.3)} 0 0` : undefined;
          const isLast = index === items.length - 1;

          return (
            <Fragment key={index}>
              {withLinkify ? addLinks(textChunk) : textChunk}
              {/* render the children inline in the last paragraph, this is used to insert a <span> to check overflow */}
              {isLast ? children : <br />}
            </Fragment>
          );
        })}
    </Text>
  );
};

const addLinks = (textValue: string) => {
  const LINKABLE_PATTERN = /\b([-\w@.:/]+\.(?:[a-z]{2,})+(?:[^ ,]+))\b/;
  const parts = textValue.split(LINKABLE_PATTERN).filter(Boolean);

  return parts.map((chunk, index) => {
    if (isUrl(chunk)) {
      let url = chunk;

      // prefix with
      if (!/^http/.test(url)) url = `http://${chunk}`;

      return (
        <Link
          key={url + index}
          href={url}
          onClick={({ event }) => {
            // stop click bubbling up to parent toggle 'Show more' handler
            event.stopPropagation();
          }}
        >
          <Text isUnderline isInline opacity={0.7}>
            {chunk}
          </Text>
        </Link>
      );
    }

    if (isEmail(chunk)) {
      return (
        <a
          key={index}
          href={`mailto:${chunk}`}
          onClick={(event) => {
            // stop click bubbling up to parent toggle 'Show more' handler
            event.stopPropagation();
          }}
        >
          <Text isUnderline isInline opacity={0.7}>
            {chunk}
          </Text>
        </a>
      );
    }

    return chunk;
  });
};

const isUrl = (string: string) => {
  const PATTERN =
    /^(https?:\/\/)?((([a-z\d-]*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(:\d+)?(\/[-a-z\d%_.@~+]*)*(\?[;&a-z\d%_.~+=-]*)?(#[-a-z\d_]*)?$/i;

  return PATTERN.test(string);
};

const isEmail = (string: string) => {
  const PATTERN =
    /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

  return PATTERN.test(string);
};

export default FormattedText;
