import {
  type RichTextItemResponse,
  type TextRichTextItemResponse,
} from '@notionhq/client/build/src/api-endpoints'
import clsx from 'clsx'
import { type ElementType, type PropsWithChildren } from 'react'

import HybridLink from './HybridLink'
import TeX, { SyncTeX } from './TeX'

function wrapWithTag(Element: ElementType, Tag: keyof JSX.IntrinsicElements) {
  return function Wrapped({ children }: PropsWithChildren) {
    return (
      <Tag>
        <Element>{children}</Element>
      </Tag>
    )
  }
}

function getWrapperFromAnnotations(
  annotations: TextRichTextItemResponse['annotations'],
) {
  let Wrapper = ({ children }: PropsWithChildren) => {
    return <>{children}</>
  }

  if (annotations.italic) {
    Wrapper = wrapWithTag(Wrapper, 'i')
  }
  if (annotations.bold) {
    Wrapper = wrapWithTag(Wrapper, 'b')
  }
  if (annotations.underline) {
    Wrapper = wrapWithTag(Wrapper, 'u')
  }
  if (annotations.code) {
    Wrapper = wrapWithTag(Wrapper, 'code')
  }
  if (annotations.code) {
    Wrapper = wrapWithTag(Wrapper, 's')
  }

  return Wrapper
}

export default function RichText({
  richText,
  rss = false,
}: {
  richText: RichTextItemResponse[]
  rss?: boolean
}) {
  return (
    <>
      {richText.map((text, index) => {
        if (text.type === 'mention') return null // TODO
        else if (text.type === 'text') {
          const Wrapper = getWrapperFromAnnotations(text.annotations)

          const className = clsx({
            italic: text.annotations.italic,
            'font-bold': text.annotations.bold,
            underline: text.annotations.underline,
            'dark:bg-neutral-800 border-1 dark:border-neutral-500 font-mono dark:text-red-400 p-1 rounded':
              text.annotations.code,
            strikethrough: text.annotations.strikethrough,
          })

          if (text.href)
            return (
              <Wrapper key={index}>
                <HybridLink
                  href={text.href}
                  className={clsx(
                    'underline transition-colors hover:text-teal-500',
                    className,
                  )}
                >
                  {text.plain_text}
                </HybridLink>
              </Wrapper>
            )
          else
            return className ? (
              <Wrapper key={index}>
                <span className={className}>{text.plain_text}</span>
              </Wrapper>
            ) : (
              <Wrapper key={index}>{text.plain_text}</Wrapper>
            )
        } else if (text.type === 'equation') {
          const Component = rss ? SyncTeX : TeX
          // @ts-expect-error Server Component
          return <Component key={index} math={text.equation.expression} />
        }
      })}
    </>
  )
}
