import React, { useState, useEffect } from 'react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { codeToHtml } from 'shiki'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Check, Copy } from 'lucide-react'
import { Button } from '@/components/ui/button'

interface CodeBlockProps {
  code: string
  language: string
}

const CodeBlock = React.memo(function CodeBlock({ code, language }: CodeBlockProps) {
  const [html, setHtml] = useState<string>('')
  const [copied, setCopied] = useState(false)

  useEffect(() => {
    let isMounted = true
    const lang = language || 'plaintext'

    codeToHtml(code, {
      lang: lang,
      theme: 'github-dark',
    })
      .then((highlightedHtml) => {
        if (isMounted) setHtml(highlightedHtml)
      })
      .catch(() => {
        // Fallback to plaintext if language is unsupported or during streaming syntax errors
        codeToHtml(code, { lang: 'plaintext', theme: 'github-dark' })
          .then((fallbackHtml) => {
            if (isMounted) setHtml(fallbackHtml)
          })
          .catch(() => {})
      })

    return () => {
      isMounted = false
    }
  }, [code, language])

  const copyToClipboard = () => {
    navigator.clipboard.writeText(code)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }

  if (!html) {
    return (
      <div className="relative my-3 rounded-xl border border-border bg-slate-950 p-4 font-mono text-xs text-emerald-400 overflow-x-auto">
        <div className="flex justify-between items-center pb-2 mb-2 border-b border-white/10 text-[10px] text-muted-foreground font-mono">
          <span>{language || 'code'}</span>
        </div>
        <pre><code>{code}</code></pre>
      </div>
    )
  }

  return (
    <div className="relative my-3 rounded-xl border border-border/80 overflow-hidden group shadow-md">
      <div className="flex justify-between items-center px-4 py-1.5 bg-slate-900 border-b border-white/10 text-xs text-muted-foreground font-mono">
        <span className="text-[11px] font-semibold text-slate-300">{language || 'code'}</span>
        <Button
          variant="ghost"
          size="icon"
          className="h-6 w-6 text-muted-foreground hover:text-foreground hover:bg-slate-800"
          onClick={copyToClipboard}
          title="Copy code"
        >
          {copied ? <Check className="w-3.5 h-3.5 text-emerald-400" /> : <Copy className="w-3.5 h-3.5" />}
        </Button>
      </div>
      <div
        className="p-4 text-xs font-mono overflow-x-auto bg-slate-950 [&>pre]:!bg-transparent [&>pre]:!p-0 [&>pre]:!m-0"
        dangerouslySetInnerHTML={{ __html: html }}
      />
    </div>
  )
})

interface MarkdownRendererProps {
  content: string
  isStreaming?: boolean
}

export const MarkdownRenderer = React.memo(function MarkdownRenderer({
  content,
  isStreaming,
}: MarkdownRendererProps) {
  return (
    <div className="prose dark:prose-invert max-w-none text-sm leading-relaxed text-foreground">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ node, ...props }) => (
            <h1 className="text-xl font-bold tracking-tight my-3 text-foreground" {...props} />
          ),
          h2: ({ node, ...props }) => (
            <h2 className="text-lg font-semibold tracking-tight my-2.5 text-foreground" {...props} />
          ),
          h3: ({ node, ...props }) => (
            <h3 className="text-base font-semibold my-2 text-foreground" {...props} />
          ),
          p: ({ node, ...props }) => (
            <p className="leading-relaxed my-2 text-foreground/90" {...props} />
          ),
          ol: ({ node, ...props }) => (
            <ol className="list-decimal list-outside ml-5 space-y-1.5 my-2" {...props} />
          ),
          ul: ({ node, ...props }) => (
            <ul className="list-disc list-outside ml-5 space-y-1.5 my-2" {...props} />
          ),
          li: ({ node, ...props }) => (
            <li className="leading-relaxed text-foreground/90 pl-0.5" {...props} />
          ),
          blockquote: ({ node, ...props }) => (
            <blockquote className="border-l-4 border-primary/80 pl-4 my-3 italic text-muted-foreground bg-primary/5 py-1 rounded-r-md" {...props} />
          ),
          strong: ({ node, ...props }) => (
            <strong className="font-semibold text-primary" {...props} />
          ),
          table: ({ node, ...props }) => (
            <div className="overflow-x-auto my-3 rounded-lg border border-border bg-card/60 shadow-sm">
              <Table className="min-w-full" {...props} />
            </div>
          ),
          thead: ({ node, ...props }) => <TableHeader {...props} />,
          tbody: ({ node, ...props }) => <TableBody {...props} />,
          tr: ({ node, ...props }) => <TableRow {...props} />,
          th: ({ node, ...props }) => <TableHead className="font-semibold text-foreground bg-muted/40" {...props} />,
          td: ({ node, ...props }) => <TableCell className="text-foreground/90" {...props} />,
          pre: ({ children }) => <>{children}</>,
          code: ({ node, className, children, ...props }: any) => {
            const contentStr = String(children || '').replace(/\n$/, '')
            const match = /language-(\w+)/.exec(className || '')
            const isMultiLine = contentStr.includes('\n')
            const isInline = !match && !isMultiLine

            if (isInline) {
              return (
                <code
                  className="bg-primary/10 text-primary border border-primary/20 px-1.5 py-0.5 rounded font-mono text-[0.85em] font-medium inline-baseline mx-0.5"
                  {...props}
                >
                  {children}
                </code>
              )
            }

            return (
              <CodeBlock
                code={contentStr}
                language={match ? match[1] : ''}
              />
            )
          },
          a: ({ node, ...props }) => (
            <a
              className="text-primary hover:underline font-medium"
              target="_blank"
              rel="noopener noreferrer"
              {...props}
            />
          ),
        }}
      >
        {content}
      </ReactMarkdown>
      {isStreaming && (
        <span className="inline-block w-2 h-4 bg-primary animate-pulse ml-1 align-middle rounded-full" />
      )}
    </div>
  )
})
