import Image from 'next/image'
import Link from 'next/link'
import parse, { attributesToProps, domToReact, Element, HTMLReactParserOptions } from 'html-react-parser'
import cx from 'classnames'
import { transformHeadlessURLs } from '@/lib/utilities'

type Props = {
  content: string | null
  replaceOptions?: Record<string, any>
  accentColor?: string
}

function mapWpClasses(classes: string): string {
  const classMappings: Record<string, string> = {
    alignleft: 'float-left',
    alignright: 'float-right',
    aligncenter: 'float-center',
  }
  const re = new RegExp(Object.keys(classMappings).join('|'), 'gi')
  return classes.replace(re, matched => {
    return classMappings[matched]
  })
}

export default function ParseContent({ content, replaceOptions, accentColor }: Props) {
  const options: HTMLReactParserOptions = {
    // @see https://github.com/remarkablemark/html-react-parser#replace
    replace: domNode => {
      if (!(domNode instanceof Element) || !domNode.attribs) return

      const { attribs, name, children } = domNode

      const props = attributesToProps(attribs)

      const classNames = props?.className && mapWpClasses(props?.className)

      // div
      if (name === 'div') {
        if (props?.className?.includes('wp-caption')) {
          return (
            <figure
              {...{ ...props, style: null }}
              {...replaceOptions?.figure}
              className={cx(classNames, replaceOptions?.figure?.className)}
            >
              {domToReact(children, options)}
            </figure>
          )
        }

        return (
          <div
            {...{ ...props, style: null }}
            {...replaceOptions?.div}
            className={cx(classNames, replaceOptions?.div?.className)}
          >
            {domToReact(children, options)}
          </div>
        )
      }

      // img
      if (name === 'img') {
        // eslint-disable-next-line jsx-a11y/alt-text
        return <Image {...props} {...replaceOptions?.img} className={cx(classNames, replaceOptions?.img?.className)} />
      }

      // a
      if (name === 'a') {
        return (
          <Link
            {...props}
            {...replaceOptions?.a}
            href={transformHeadlessURLs(props.href)}
            className={cx('underline', classNames, replaceOptions?.a?.className)}
          >
            {domToReact(children, options)}
          </Link>
        )
      }

      // p
      if (name === 'p') {
        if (props?.className?.includes('wp-caption-text')) {
          return (
            <figcaption
              {...props}
              {...replaceOptions?.figcaption}
              className={cx('pt-2 text-caption', classNames, replaceOptions?.figcaption?.className)}
            >
              {domToReact(children, options)}
            </figcaption>
          )
        }

        const { textClass = null, ...parsedReplaceOptions } = { textClass: null, ...replaceOptions?.p }

        return (
          <p
            {...props}
            {...parsedReplaceOptions}
            className={cx(textClass ?? 'text-body-lg', classNames, parsedReplaceOptions?.className)}
          >
            {domToReact(children, options)}
          </p>
        )
      }

      // h[1-6]
      if (['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(name)) {
        const Component = name

        return (
          <Component
            {...props}
            {...replaceOptions?.[name]}
            className={cx(`text-${name}`, classNames, replaceOptions?.[name]?.className)}
          >
            {domToReact(children, options)}
          </Component>
        )
      }

      // blockquote
      if (name === 'blockquote') {
        return (
          <blockquote
            {...props}
            {...replaceOptions?.blockquote}
            className={cx('text-pull-quote', classNames, replaceOptions?.blockquote?.className)}
          >
            {domToReact(children)}
          </blockquote>
        )
      }

      // ul
      if (name === 'ul') {
        return (
          <ul {...props} {...replaceOptions?.ul} className={cx(classNames, replaceOptions?.ul?.className)}>
            {domToReact(children, options)}
          </ul>
        )
      }

      // ol
      if (name === 'ol') {
        return (
          <ol {...props} {...replaceOptions?.ol} className={cx(classNames, replaceOptions?.ol?.className)}>
            {domToReact(children, options)}
          </ol>
        )
      }

      // dl
      if (name === 'dl') {
        return (
          <dl {...props} {...replaceOptions?.dl} className={cx(classNames, replaceOptions?.dl?.className)}>
            {domToReact(children, options)}
          </dl>
        )
      }

      // hr
      if (name === 'hr') {
        return (
          <hr
            {...props}
            {...replaceOptions?.hr}
            className={cx('border-none h-1 bg-black', classNames, replaceOptions?.hr?.className)}
          />
        )
      }

      // pre
      if (name === 'pre') {
        return (
          <pre
            {...props}
            {...replaceOptions?.pre}
            className={cx('whitespace-pre-wrap', classNames, replaceOptions?.pre?.className)}
          >
            {domToReact(children, options)}
          </pre>
        )
      }

      // iframe
      if (name === 'iframe') {
        const isVideoEmbed = Boolean(props?.src.match(/(youtube|youtu.be|vimeo)/g))

        const videoProps = {
          ...props,
          width: '',
          height: '',
        }

        return (
          <iframe
            {...(isVideoEmbed ? videoProps : props)}
            loading="lazy"
            {...replaceOptions?.iframe}
            className={cx('w-full aspect-video', classNames, replaceOptions?.iframe?.className)}
          />
        )
      }
    },
  }

  return (
    <div className={cx('grid gap-y-8 wysiwyg', accentColor && `wysiwyg--${accentColor}`)}>
      {parse(content || '', options)}
    </div>
  )
}
