import { memo, useEffect, useMemo, useRef } from 'react'
import { motion } from 'framer-motion'
import { Copy, FileText, Pencil, RefreshCw, Sparkles, Volume2, VolumeX } from 'lucide-react'
import { renderMarkdown } from '../../utils/markdown'
import TypingIndicator from './TypingIndicator'

function addCodeCopyButtons(container) {
  container.querySelectorAll('pre').forEach((pre) => {
    if (pre.dataset.enhanced === 'true') return
    pre.dataset.enhanced = 'true'
    const wrapper = document.createElement('div')
    wrapper.className = 'code-shell'
    const toolbar = document.createElement('div')
    toolbar.className = 'code-toolbar'
    const badge = document.createElement('span')
    badge.className = 'code-badge'
    badge.textContent = pre.querySelector('code')?.className?.replace('hljs language-', '') || 'code'
    const button = document.createElement('button')
    button.className = 'code-copy-button'
    button.type = 'button'
    button.textContent = 'Copy'
    button.addEventListener('click', async () => {
      const code = pre.querySelector('code')?.textContent || pre.textContent || ''
      await navigator.clipboard.writeText(code)
      button.textContent = 'Copied'
      window.setTimeout(() => {
        button.textContent = 'Copy'
      }, 1400)
    })
    toolbar.appendChild(badge)
    toolbar.appendChild(button)
    pre.parentNode.insertBefore(wrapper, pre)
    wrapper.appendChild(toolbar)
    wrapper.appendChild(pre)
  })
}

function MessageBubble({
  message,
  user,
  onCopyMessage,
  onRegenerate,
  onEdit,
  onSpeak,
  onPreviewFile,
  speaking,
}) {
  const isUser = message.role === 'user'
  const contentRef = useRef(null)

  const html = useMemo(
    () => (isUser ? '' : renderMarkdown(message.content || '')),
    [isUser, message.content],
  )

  useEffect(() => {
    if (!isUser && contentRef.current) {
      addCodeCopyButtons(contentRef.current)
    }
  }, [html, isUser])

  return (
    <motion.article
      initial={{ opacity: 0, y: 16 }}
      animate={{ opacity: 1, y: 0 }}
      className={`group mx-auto flex w-full max-w-4xl gap-3 px-4 py-3 sm:px-6 ${
        isUser ? 'justify-end' : 'justify-start'
      }`}
    >
      {!isUser ? (
        <div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-accent/12 text-accent shadow-soft">
          <Sparkles className="h-4 w-4" />
        </div>
      ) : null}

      <div
        className={`max-w-[min(100%,54rem)] rounded-[28px] border px-4 py-4 shadow-soft sm:px-5 ${
          isUser
            ? 'border-accent/20 bg-accent text-accent-foreground'
            : 'border-border/70 bg-panel text-foreground'
        }`}
      >
        {message.attachments?.length ? (
          <div className="mb-3 flex flex-wrap gap-2">
            {message.attachments.map((attachment, index) => (
              <button
                key={`${attachment.filename}-${index}`}
                type="button"
                onClick={() => onPreviewFile(attachment)}
                className={`inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs font-medium ${
                  isUser
                    ? 'border-white/20 bg-white/10 text-white/90'
                    : 'border-border bg-background text-muted-foreground hover:text-foreground'
                }`}
              >
                <FileText className="h-3.5 w-3.5" />
                {attachment.filename}
              </button>
            ))}
          </div>
        ) : null}

        {isUser ? (
          <p className="whitespace-pre-wrap break-words text-sm leading-7">{message.content}</p>
        ) : message.streaming && !message.content ? (
          <TypingIndicator />
        ) : (
          <div
            ref={contentRef}
            className="markdown-body text-sm leading-7"
            dangerouslySetInnerHTML={{ __html: html }}
          />
        )}

        {!isUser && message.streaming && message.content ? <span className="typing-cursor" /> : null}

        <div className="mt-4 flex flex-wrap items-center gap-2">
          {!isUser ? (
            <>
              <MessageAction icon={Copy} label="Copy" onClick={() => onCopyMessage(message)} />
              <MessageAction
                icon={speaking ? VolumeX : Volume2}
                label={speaking ? 'Stop audio' : 'Read aloud'}
                onClick={() => onSpeak(message)}
              />
              <MessageAction
                icon={RefreshCw}
                label="Regenerate"
                onClick={() => onRegenerate(message.id)}
              />
            </>
          ) : (
            <MessageAction icon={Pencil} label="Edit & branch" onClick={() => onEdit(message)} />
          )}

          {message.model_used ? (
            <>
            <span className="hidden ml-auto rounded-full border border-border/80 bg-background px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
              {(message.provider || 'assistant').replaceAll('-', ' ')} · {message.model_used}
            </span>
            <span className="ml-auto rounded-full border border-border/80 bg-background px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
              {`${(message.provider || 'assistant').replaceAll('-', ' ')} / ${message.model_used}`}
            </span>
            </>
          ) : null}
        </div>
      </div>

      {isUser ? (
        <div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl border border-border/70 bg-card text-sm font-semibold text-foreground shadow-soft">
          {user?.avatar_url ? (
            <img src={user.avatar_url} alt={user.username} className="h-full w-full rounded-2xl object-cover" />
          ) : (
            (user?.username || 'You').slice(0, 1).toUpperCase()
          )}
        </div>
      ) : null}
    </motion.article>
  )
}

function MessageAction({ icon: Icon, label, onClick }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className="inline-flex items-center gap-1.5 rounded-full border border-border/70 bg-background px-3 py-1.5 text-xs font-medium text-muted-foreground transition hover:border-accent/20 hover:text-foreground"
    >
      <Icon className="h-3.5 w-3.5" />
      {label}
    </button>
  )
}

export default memo(MessageBubble)
