import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'
import type { NodeViewProps } from '@tiptap/react'
import { useState, useCallback, useRef, useEffect } from 'react'
import { getLanguageIconUrl, getLanguageDisplayName, SUPPORTED_LANGUAGES } from './icons'
import { Icons } from '../../../shared/Icons'

export function CodeBlockView({ node, updateAttributes }: NodeViewProps) {
  const { language, title } = node.attrs
  const [showLanguageMenu, setShowLanguageMenu] = useState(false)
  const [copied, setCopied] = useState(false)
  const [isEditingTitle, setIsEditingTitle] = useState(false)
  const [titleValue, setTitleValue] = useState(title || '')
  const titleInputRef = useRef<HTMLInputElement>(null)
  const menuRef = useRef<HTMLDivElement>(null)

  const iconUrl = language ? getLanguageIconUrl(language) : null
  const displayName = language ? getLanguageDisplayName(language) : 'Plain text'

  const handleCopy = useCallback(async () => {
    const code = node.textContent
    await navigator.clipboard.writeText(code)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }, [node.textContent])

  const handleLanguageSelect = useCallback((lang: string) => {
    updateAttributes({ language: lang })
    setShowLanguageMenu(false)
  }, [updateAttributes])

  const handleTitleSubmit = useCallback(() => {
    updateAttributes({ title: titleValue || null })
    setIsEditingTitle(false)
  }, [titleValue, updateAttributes])

  const handleTitleKeyDown = useCallback((e: React.KeyboardEvent) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      handleTitleSubmit()
    }
    if (e.key === 'Escape') {
      setTitleValue(title || '')
      setIsEditingTitle(false)
    }
  }, [handleTitleSubmit, title])

  useEffect(() => {
    if (isEditingTitle && titleInputRef.current) {
      titleInputRef.current.focus()
      titleInputRef.current.select()
    }
  }, [isEditingTitle])

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        setShowLanguageMenu(false)
      }
    }
    if (showLanguageMenu) {
      document.addEventListener('mousedown', handleClickOutside)
    }
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [showLanguageMenu])


  return (
    <NodeViewWrapper className="code-block-wrapper relative my-6">
      {/* Header bar */}
      <div className="flex items-center gap-2 px-3 py-2 bg-zinc-50 border border-zinc-200 border-b-0 rounded-t-md">
        {/* Language selector */}
        <div className="relative" ref={menuRef}>
          <button
            type="button"
            onClick={() => setShowLanguageMenu(!showLanguageMenu)}
            className="flex items-center gap-1.5 px-2 py-1 text-xs text-zinc-600 hover:text-zinc-900 hover:bg-zinc-100 rounded transition-colors"
            contentEditable={false}
          >
            {iconUrl && (
              <img src={iconUrl} alt="" className="w-3.5 h-3.5" />
            )}
            <span>{displayName}</span>
            <Icons.ChevronDown className="w-3 h-3 opacity-50" />
          </button>

          {showLanguageMenu && (
            <div className="absolute top-full left-0 mt-1 w-48 max-h-64 overflow-y-auto bg-white border border-zinc-200 rounded-md shadow-lg z-50">
              {SUPPORTED_LANGUAGES.map((lang) => {
                const langIcon = getLanguageIconUrl(lang)
                return (
                  <button
                    key={lang}
                    type="button"
                    onClick={() => handleLanguageSelect(lang)}
                    className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs text-left hover:bg-zinc-50 transition-colors ${
                      language === lang ? 'bg-zinc-100 text-zinc-900' : 'text-zinc-600'
                    }`}
                  >
                    {langIcon && <img src={langIcon} alt="" className="w-3.5 h-3.5" />}
                    <span>{getLanguageDisplayName(lang)}</span>
                  </button>
                )
              })}
            </div>
          )}
        </div>


        {/* Divider */}
        <div className="w-px h-4 bg-zinc-200" />

        {/* Title (editable) */}
        <div className="flex-1 min-w-0">
          {isEditingTitle ? (
            <input
              ref={titleInputRef}
              type="text"
              value={titleValue}
              onChange={(e) => setTitleValue(e.target.value)}
              onBlur={handleTitleSubmit}
              onKeyDown={handleTitleKeyDown}
              placeholder="filename.ext"
              className="w-full px-1 py-0.5 text-xs bg-white border border-zinc-300 rounded focus:outline-none focus:border-zinc-400"
              contentEditable={false}
            />
          ) : (
            <button
              type="button"
              onClick={() => {
                setTitleValue(title || '')
                setIsEditingTitle(true)
              }}
              className="text-xs text-zinc-500 hover:text-zinc-700 truncate max-w-full"
              contentEditable={false}
            >
              {title || 'Add title...'}
            </button>
          )}
        </div>

        {/* Copy button */}
        <button
          type="button"
          onClick={handleCopy}
          className="flex items-center gap-1 px-2 py-1 text-xs text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 rounded transition-colors"
          contentEditable={false}
        >
          {copied ? (
            <>
              <Icons.Check className="w-3 h-3 text-emerald-500" />
              <span className="text-emerald-600">Copied</span>
            </>
          ) : (
            <>
              <Icons.Copy className="w-3 h-3" />
              <span>Copy</span>
            </>
          )}
        </button>
      </div>

      {/* Code content */}
      <pre className="!mt-0 !rounded-t-none">
        <code className={language ? `language-${language}` : ''}>
          <NodeViewContent />
        </code>
      </pre>
    </NodeViewWrapper>
  )
}
