/*
 *  Markdown.tsx
 *  Zyquo Cloud Web
 *
 *  Author: Simon-Pierre Boucher
 *  Mail: contact@spboucher.ai
 *
 *  Assistant message rendering: GitHub-flavored Markdown with syntax-
 *  highlighted code blocks (language label, copy, wrap toggle) mapped to the
 *  Zyquo syntax tokens. Memoized — re-parsing only when text changes.
 */

import { lazy, memo, Suspense, useState, type ReactNode } from 'react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import rehypeHighlight from 'rehype-highlight'
import rehypeKatex from 'rehype-katex'
import 'katex/dist/katex.min.css'
import { IconCheck, IconCopy } from './icons'

const Mermaid = lazy(() => import('./Mermaid'))

function extractText(node: ReactNode): string {
  if (typeof node === 'string') return node
  if (Array.isArray(node)) return node.map(extractText).join('')
  if (node && typeof node === 'object' && 'props' in node) {
    return extractText((node as { props: { children?: ReactNode } }).props.children)
  }
  return ''
}

function CodeBlock({ className, children }: { className?: string; children?: ReactNode }) {
  const [copied, setCopied] = useState(false)
  const [wrap, setWrap] = useState(false)
  const language = /language-(\w+)/.exec(className ?? '')?.[1] ?? ''

  const copy = () => {
    void navigator.clipboard.writeText(extractText(children).replace(/\n$/, ''))
    setCopied(true)
    setTimeout(() => setCopied(false), 1200)
  }

  return (
    <div className="code-block">
      <div className="code-block-header">
        <span>{language || 'text'}</span>
        <span className={`code-block-actions${copied ? ' confirming' : ''}`}>
          <button className="code-block-copy" onClick={() => setWrap((w) => !w)}>
            {wrap ? 'unwrap' : 'wrap'}
          </button>
          <button className={`code-block-copy${copied ? ' ok' : ''}`} onClick={copy}>
            {copied ? <IconCheck size={10} /> : <IconCopy size={10} />} {copied ? 'copied' : 'copy'}
          </button>
        </span>
      </div>
      <pre className={wrap ? 'wrap' : ''}>
        <code className={className}>{children}</code>
      </pre>
    </div>
  )
}

export const Markdown = memo(function Markdown({ text }: { text: string }) {
  return (
    <div className="markdown">
      <ReactMarkdown
        remarkPlugins={[remarkGfm, remarkMath]}
        rehypePlugins={[
          [rehypeHighlight, { detect: false, ignoreMissing: true }],
          [rehypeKatex, { errorColor: 'var(--z-danger)' }],
        ]}
        components={{
          pre: ({ children }) => <>{children}</>,
          code: ({ className, children, ...props }) => {
            const inline = !className && typeof children === 'string' && !children.includes('\n')
            if (inline) {
              return (
                <code className={className} {...props}>
                  {children}
                </code>
              )
            }
            if (/language-mermaid/.test(className ?? '')) {
              return (
                <Suspense
                  fallback={
                    <div style={{ color: 'var(--z-text-tertiary)', fontSize: 12 }}>
                      Rendering diagram…
                    </div>
                  }
                >
                  <Mermaid code={extractText(children).replace(/\n$/, '')} />
                </Suspense>
              )
            }
            return <CodeBlock className={className}>{children}</CodeBlock>
          },
          a: ({ href, children }) => (
            <a href={href} target="_blank" rel="noreferrer noopener">
              {children}
            </a>
          ),
        }}
      >
        {text}
      </ReactMarkdown>
    </div>
  )
})
