import type { Components } from 'react-markdown'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
import { cn } from '@/lib/utils'
import { Scrollbar } from '../basic/scrollbar'

export interface MarkdownBodyProps {
  children: string
  className?: string
}

const markdownComponents: Components = {
  p: ({ children }) => (
    <p className="text-sm leading-sm text-text [&:not(:first-child)]:mt-6 last:mb-0">{children}</p>
  ),
  h1: ({ children }) => (
    <h1 className="scroll-m-20 text-4xl font-medium tracking-tight text-text">{children}</h1>
  ),
  h2: ({ children }) => (
    <h2 className="scroll-m-20 border-b border-border-secondary pb-2 text-3xl font-semibold tracking-tight text-text first:mt-0 [&:not(:first-child)]:mt-10">
      {children}
    </h2>
  ),
  h3: ({ children }) => (
    <h3 className="scroll-m-20 text-2xl font-semibold tracking-tight text-text [&:not(:first-child)]:mt-8">
      {children}
    </h3>
  ),
  h4: ({ children }) => (
    <h4 className="scroll-m-20 text-xl font-semibold tracking-tight text-text [&:not(:first-child)]:mt-6">
      {children}
    </h4>
  ),
  h5: ({ children }) => (
    <h5 className="scroll-m-20 text-lg font-semibold tracking-tight text-text-secondary [&:not(:first-child)]:mt-4">
      {children}
    </h5>
  ),
  h6: ({ children }) => (
    <h6 className="scroll-m-20 text-base font-semibold tracking-tight text-text-tertiary uppercase [&:not(:first-child)]:mt-4">
      {children}
    </h6>
  ),
  blockquote: ({ children }) => (
    <blockquote className="mt-6 border-l-2 border-border-secondary pl-6 italic text-text-secondary">
      {children}
    </blockquote>
  ),
  ul: ({ className, children }) => (
    <ul
      className={cn(
        'my-6 ml-6 text-text [&>li]:mt-2',
        String(className ?? '').includes('contains-task-list') ? 'list-none' : 'list-disc'
      )}
    >
      {children}
    </ul>
  ),
  ol: ({ children }) => (
    <ol className="my-6 ml-6 list-decimal text-text [&>li]:mt-2">{children}</ol>
  ),
  li: ({ className, children }) => (
    <li
      className={cn(
        'leading-sm',
        String(className ?? '').includes('task-list-item') &&
          'list-none flex items-start gap-2 [&>input]:mt-0.5 [&>input]:shrink-0'
      )}
    >
      {children}
    </li>
  ),
  pre: ({ children }) => (
    <Scrollbar
      scrollbarVisibility="auto"
      className="my-6 rounded-lg border border-border-tertiary bg-bg-base p-4 font-mono text-sm leading-sm text-text"
    >
      <pre className="m-0 font-mono text-sm leading-sm text-text border-0 bg-transparent p-0">
        {children}
      </pre>
    </Scrollbar>
  ),
  code: ({ className, children, ...props }) => {
    const isBlock = typeof className === 'string' && className.startsWith('language-')
    if (!isBlock) {
      return (
        <code
          className="relative rounded bg-fill-tertiary px-1 py-0.5 font-mono text-sm leading-sm font-semibold text-text"
          {...props}
        >
          {children}
        </code>
      )
    }
    return (
      <code className={cn(className, 'font-mono text-sm leading-sm')} {...props}>
        {children}
      </code>
    )
  },
  table: ({ children }) => (
    <Scrollbar
      scrollbarVisibility="auto"
      className="my-6 w-full rounded-md border border-border-secondary"
    >
      <table className="w-full border-collapse text-sm leading-sm text-text">{children}</table>
    </Scrollbar>
  ),
  thead: ({ children }) => (
    <thead className="border-b border-border-secondary bg-fill-tertiary">{children}</thead>
  ),
  tbody: ({ children }) => (
    <tbody className="[&>tr]:border-b [&>tr]:border-border-tertiary">{children}</tbody>
  ),
  tr: ({ children }) => <tr>{children}</tr>,
  th: ({ children }) => (
    <th className="px-4 py-2 text-left font-semibold text-text">{children}</th>
  ),
  td: ({ children }) => <td className="px-4 py-2 text-text">{children}</td>,
  a: ({ href, children }) => (
    <a href={href} target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
      {children}
    </a>
  ),
  hr: () => <hr className="my-6 border-0 border-t border-border-secondary" />,
  strong: ({ children }) => <strong className="font-semibold text-text">{children}</strong>,
  em: ({ children }) => <em className="italic text-text">{children}</em>,
}

export function MarkdownBody({ children, className }: MarkdownBodyProps) {
  return (
    <div className={cn('markdown-body text-sm leading-sm text-text', className)}>
      <ReactMarkdown
        remarkPlugins={[remarkGfm, remarkMath]}
        rehypePlugins={[rehypeKatex]}
        components={markdownComponents}
      >
        {children}
      </ReactMarkdown>
    </div>
  )
}

MarkdownBody.displayName = 'MarkdownBody'
