import katex, { type KatexOptions, ParseError } from 'katex'
import { type ComponentProps, type ReactElement } from 'react'

export type Props<T extends keyof JSX.IntrinsicElements = 'div'> =
  ComponentProps<T> &
    Partial<{
      as: T
      block: boolean
      errorColor: string
      renderError: (error: ParseError | TypeError) => ReactElement
      settings: KatexOptions
    }> & {
      math: string
    }

/**
 * This is only used for the RSS feed
 */
export function SyncTeX({
  children,
  math,
  block,
  errorColor,
  renderError,
  settings,
  as: asComponent,
  ...props
}: Props) {
  const Component = asComponent || (block ? 'div' : 'span')
  const content = (children ?? math) as string

  let innerHtml: string
  try {
    innerHtml = katex.renderToString(content, {
      displayMode: !!block,
      errorColor,
      throwOnError: !!renderError,
      ...settings,
    })
  } catch (error) {
    if (error instanceof ParseError || error instanceof TypeError) {
      if (renderError) {
        return renderError(error)
      } else {
        innerHtml = error.message
      }
    } else {
      throw error
    }
  }

  return (
    <Component {...props} dangerouslySetInnerHTML={{ __html: innerHtml }} />
  )
}

export default async function TeX(props: Props) {
  // @ts-expect-error CSS not JS
  await import('katex/dist/katex.min.css')

  return <SyncTeX {...props} />
}
