import { EditorContent, useEditor } from '@tiptap/react'
import Link from '@tiptap/extension-link'
import Placeholder from '@tiptap/extension-placeholder'
import Underline from '@tiptap/extension-underline'
import { Markdown } from '@tiptap/markdown'
import StarterKit from '@tiptap/starter-kit'
import { Card, Splitter, theme } from 'antd'
import PropTypes from 'prop-types'
import { useEffect, useRef, useState } from 'react'
import { useThemeContext } from '../context/ThemeContext'
import MarkdownToolbar from './MarkdownToolbar'
import CodeBlockEditor from './CodeBlockEditor'

const MarkdownInput = ({
  value,
  onChange,
  minHeight = '120px',
  size = 'small',
  showCard = true
}) => {
  const markdownValue = typeof value === 'string' ? value : ''
  const lastMarkdownRef = useRef(markdownValue)
  const { isDarkMode } = useThemeContext()
  const { token } = theme.useToken()
  const [viewState, setViewState] = useState({ editor: true, code: false })
  const [focusedPanel, setFocusedPanel] = useState(null)
  const editorPanelRef = useRef(null)
  const codePanelRef = useRef(null)

  const handlePanelBlur = () => {
    requestAnimationFrame(() => {
      const active = document.activeElement
      if (editorPanelRef.current?.contains(active)) {
        setFocusedPanel('editor')
      } else if (codePanelRef.current?.contains(active)) {
        setFocusedPanel('code')
      } else {
        setFocusedPanel(null)
      }
    })
  }
  const editor = useEditor({
    extensions: [
      StarterKit,
      Link.configure({
        autolink: true,
        defaultProtocol: 'https',
        openOnClick: false
      }),
      Placeholder.configure({
        placeholder: 'Enter text here...'
      }),
      Underline,
      Markdown
    ],
    content: markdownValue,
    contentType: 'markdown',
    editorProps: {
      attributes: {
        class: 'md-editor__content'
      }
    },
    immediatelyRender: false,
    onUpdate: ({ editor }) => {
      const nextMarkdown = editor.getMarkdown()
      lastMarkdownRef.current = nextMarkdown
      onChange?.(nextMarkdown)
    }
  })

  useEffect(() => {
    if (!editor) {
      return
    }

    if (markdownValue !== lastMarkdownRef.current) {
      editor.commands.setContent(markdownValue, {
        contentType: 'markdown',
        emitUpdate: false
      })
      lastMarkdownRef.current = markdownValue
    }
  }, [editor, markdownValue])

  const editorPanel = (
    <div
      ref={editorPanelRef}
      className='markdown md-editor'
      onFocusCapture={() => setFocusedPanel('editor')}
      onBlurCapture={handlePanelBlur}
    >
      <EditorContent editor={editor} />
    </div>
  )

  const codePanel = (
    <div
      ref={codePanelRef}
      className='markdown-code-editor'
      onFocusCapture={() => setFocusedPanel('code')}
      onBlurCapture={handlePanelBlur}
    >
      <CodeBlockEditor
        code={markdownValue}
        language='markdown'
        showLineNumbers={false}
        style={{ border: 'none' }}
        onChange={(val) => {
          onChange?.(val)
        }}
      />
    </div>
  )

  const renderContent = () => {
    if (viewState.editor && viewState.code) {
      return (
        <Splitter
          className='farmcontrol-splitter markdown-splitter'
          vertical={true}
        >
          {viewState.editor && (
            <Splitter.Panel style={{ minHeight: 80 }}>
              {editorPanel}
            </Splitter.Panel>
          )}
          {viewState.code && (
            <Splitter.Panel style={{ minHeight: 80 }}>
              {codePanel}
            </Splitter.Panel>
          )}
        </Splitter>
      )
    }
    if (viewState.code) {
      return codePanel
    }
    return editorPanel
  }

  const cardContent = (
    <div
      className={isDarkMode ? 'dark-theme' : 'light-theme'}
      style={{
        '--basePageBg': token.colorBgContainer,
        '--baseBase': token.colorBgContainer,
        '--baseBgSubtle': token.colorBgElevated,
        '--baseBg': token.colorFillTertiary,
        '--baseBgHover': token.colorFillSecondary,
        '--baseBgActive': token.colorFill,
        '--baseLine': token.colorBorderSecondary,
        '--baseBorder': token.colorBorder,
        '--baseBorderHover': token.colorTextTertiary,
        '--baseSolid': token.colorTextTertiary,
        '--baseSolidHover': token.colorTextSecondary,
        '--baseText': token.colorText,
        '--baseTextContrast': token.colorText,
        '--accentBase': token.colorPrimaryBg,
        '--accentBgSubtle': token.colorPrimaryBg,
        '--accentBg': token.colorPrimaryBgHover,
        '--accentBgHover': token.colorPrimaryHover,
        '--accentBgActive': token.colorPrimaryActive,
        '--accentLine': token.colorPrimaryBorder,
        '--accentBorder': token.colorPrimaryBorderHover,
        '--accentBorderHover': token.colorPrimaryHover,
        '--accentSolid': token.colorPrimary,
        '--accentSolidHover': token.colorPrimaryHover,
        '--accentText': token.colorPrimary,
        '--accentTextContrast': token.colorWhite,
        '--md-editor-min-height': minHeight
      }}
    >
      <MarkdownToolbar
        editor={editor}
        size={size}
        showCard={showCard}
        viewState={viewState}
        onViewStateChange={setViewState}
        editingToolsDisabled={
          focusedPanel === 'code' || (viewState.code && !viewState.editor)
        }
      />
      {renderContent()}
    </div>
  )

  return (
    <>
      {showCard ? (
        <Card
          style={{ height: '100%' }}
          styles={{
            body: {
              height: '100%',
              padding: 0,
              overflow: 'auto'
            }
          }}
        >
          {cardContent}
        </Card>
      ) : (
        cardContent
      )}
    </>
  )
}

MarkdownInput.propTypes = {
  value: PropTypes.string,
  onChange: PropTypes.func,
  minHeight: PropTypes.string,
  size: PropTypes.string,
  showCard: PropTypes.bool
}

export default MarkdownInput
