import { ElementDefinition } from '@/entity/element/model/interface'
import { CellsBadge } from '@/entity/element/ui/cellsBadge'
import {
  Bold,
  Code,
  FileText,
  Heading1,
  Heading2,
  Heading3,
  Italic,
  Link,
  List,
  ListOrdered,
  Quote,
  Strikethrough,
  Table,
} from 'lucide-react'
import { useState } from 'react'
import ReactMarkdown, { Components } from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import rehypeSanitize from 'rehype-sanitize'
import remarkGfm from 'remark-gfm'
import { Button } from 'shared/ui/button'
import { Label } from 'shared/ui/label'
import { Textarea } from 'shared/ui/textarea'

interface NoteConfig {
  content?: string // Основное содержимое markdown
  targetCells: any[]
  name?: string
  id?: string
}

// Компонент панели инструментов
const MarkdownToolbar = ({
  onInsert,
  disabled = false,
}: {
  onInsert: (text: string) => void
  disabled?: boolean
}) => {
  const tools = [
    { icon: Bold, label: 'Жирный', syntax: '**текст**' },
    { icon: Italic, label: 'Курсив', syntax: '*текст*' },
    { icon: Strikethrough, label: 'Зачеркнутый', syntax: '~~текст~~' },
    { icon: Heading1, label: 'Заголовок 1', syntax: '# Заголовок' },
    { icon: Heading2, label: 'Заголовок 2', syntax: '## Заголовок' },
    { icon: Heading3, label: 'Заголовок 3', syntax: '### Заголовок' },
    { icon: List, label: 'Список', syntax: '- Элемент списка' },
    {
      icon: ListOrdered,
      label: 'Нумерованный список',
      syntax: '1. Элемент списка',
    },
    { icon: Quote, label: 'Цитата', syntax: '> Цитата' },
    { icon: Code, label: 'Код', syntax: '`код`' },
    { icon: Link, label: 'Ссылка', syntax: '[текст](url)' },
    {
      icon: Table,
      label: 'Таблица',
      syntax:
        '| Колонка 1 | Колонка 2 |\n|-----------|----------|\n| Ячейка 1  | Ячейка 2  |',
    },
  ]

  return (
    <div className="flex flex-wrap gap-1 border-b border-gray-200 bg-gray-50 p-2">
      {tools.map((tool, index) => (
        <Button
          key={index}
          variant="ghost"
          size="sm"
          onClick={() => onInsert(tool.syntax)}
          disabled={disabled}
          className="h-8 w-8 p-0"
          title={tool.label}
        >
          <tool.icon className="h-3 w-3" />
        </Button>
      ))}
    </div>
  )
}

// Компонент предварительного просмотра markdown
const MarkdownPreview = ({ content }: { content: string }) => {
  return (
    <div className="prose prose-sm max-w-none">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        rehypePlugins={[rehypeRaw, rehypeSanitize]}
        components={
          {
            // Кастомные стили для компонентов
            h1: ({ children }: { children: React.ReactNode }) => (
              <h1 className="mb-2 text-lg font-bold">{children}</h1>
            ),
            h2: ({ children }: { children: React.ReactNode }) => (
              <h2 className="mb-2 text-base font-bold">{children}</h2>
            ),
            h3: ({ children }: { children: React.ReactNode }) => (
              <h3 className="mb-2 text-sm font-bold">{children}</h3>
            ),
            p: ({ children }: { children: React.ReactNode }) => (
              <p className="mb-2 text-sm">{children}</p>
            ),
            ul: ({ children }: { children: React.ReactNode }) => (
              <ul className="mb-2 list-inside list-disc text-sm">{children}</ul>
            ),
            ol: ({ children }: { children: React.ReactNode }) => (
              <ol className="mb-2 list-inside list-decimal text-sm">
                {children}
              </ol>
            ),
            li: ({ children }: { children: React.ReactNode }) => (
              <li className="mb-1">{children}</li>
            ),
            blockquote: ({ children }: { children: React.ReactNode }) => (
              <blockquote className="mb-2 border-l-4 border-gray-300 pl-4 italic text-gray-600">
                {children}
              </blockquote>
            ),
            code: ({ children }: { children: React.ReactNode }) => (
              <code className="rounded bg-gray-100 px-1 py-0.5 font-mono text-xs">
                {children}
              </code>
            ),
            pre: ({ children }: { children: React.ReactNode }) => (
              <pre className="mb-2 overflow-auto rounded bg-gray-100 p-2 font-mono text-xs">
                {children}
              </pre>
            ),
            table: ({ children }: { children: React.ReactNode }) => (
              <table className="mb-2 w-full border-collapse border border-gray-300 text-xs">
                {children}
              </table>
            ),
            th: ({ children }: { children: React.ReactNode }) => (
              <th className="border border-gray-300 bg-gray-100 px-2 py-1 font-semibold">
                {children}
              </th>
            ),
            td: ({ children }: { children: React.ReactNode }) => (
              <td className="border border-gray-300 px-2 py-1">{children}</td>
            ),
            a: ({
              children,
              href,
            }: {
              children: React.ReactNode
              href?: string
            }) => (
              <a
                href={href}
                className="text-blue-600 underline"
                target="_blank"
                rel="noopener noreferrer"
              >
                {children}
              </a>
            ),
          } as Components
        }
      >
        {content || '*Введите текст для предварительного просмотра...*'}
      </ReactMarkdown>
    </div>
  )
}

export const noteDefinition: ElementDefinition<NoteConfig, string> = {
  type: 'note',
  label: 'Заметка',
  icon: <FileText className="h-4 w-4" />,
  version: 1,
  defaultConfig: {
    content: '',
    targetCells: [],
    name: '',
  },
  getInitialValue: config => {
    return config.content || ''
  },
  mapToCells: config => config.targetCells || [],
  mapToCellValues: (config, value) => {
    const cells = config.targetCells || []
    return cells.map(target => ({ target, value: value || '' }))
  },
  Editor: ({ config, onChange }) => {
    const [markdownContent, setMarkdownContent] = useState(config.content || '')

    const handleContentChange = (value: string) => {
      setMarkdownContent(value)
      onChange({ ...config, content: value })
    }

    const insertText = (syntax: string) => {
      const textarea = document.querySelector(
        'textarea[data-markdown-editor]'
      ) as HTMLTextAreaElement
      if (!textarea) return

      const start = textarea.selectionStart
      const end = textarea.selectionEnd
      const selectedText = markdownContent.substring(start, end)

      let insertedText = syntax
      let cursorPosition = start + insertedText.length

      if (selectedText) {
        // Если есть выделенный текст, оборачиваем его соответствующим синтаксисом
        if (syntax.includes('**текст**')) {
          insertedText = `**${selectedText}**`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('*текст*')) {
          insertedText = `*${selectedText}*`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('~~текст~~')) {
          insertedText = `~~${selectedText}~~`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('`код`')) {
          insertedText = `\`${selectedText}\``
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('[текст](url)')) {
          insertedText = `[${selectedText}](url)`
          cursorPosition = start + selectedText.length + 3 // Курсор на "url"
        } else if (syntax.includes('# Заголовок')) {
          insertedText = `# ${selectedText}`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('## Заголовок')) {
          insertedText = `## ${selectedText}`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('### Заголовок')) {
          insertedText = `### ${selectedText}`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('> Цитата')) {
          insertedText = `> ${selectedText}`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('- Элемент списка')) {
          insertedText = `- ${selectedText}`
          cursorPosition = start + insertedText.length
        } else if (syntax.includes('1. Элемент списка')) {
          insertedText = `1. ${selectedText}`
          cursorPosition = start + insertedText.length
        } else {
          // Для остальных случаев просто заменяем placeholder
          insertedText = syntax.replace('текст', selectedText)
          cursorPosition = start + insertedText.length
        }
      } else {
        // Если нет выделенного текста, вставляем шаблон
        insertedText = syntax

        // Позиционируем курсор внутри шаблона для редактирования
        if (syntax.includes('**текст**')) {
          cursorPosition = start + 2 // После **
        } else if (syntax.includes('*текст*')) {
          cursorPosition = start + 1 // После *
        } else if (syntax.includes('~~текст~~')) {
          cursorPosition = start + 2 // После ~~
        } else if (syntax.includes('`код`')) {
          cursorPosition = start + 1 // После `
        } else if (syntax.includes('[текст](url)')) {
          cursorPosition = start + 1 // После [
        } else if (syntax.includes('# Заголовок')) {
          cursorPosition = start + 2 // После "# "
        } else if (syntax.includes('## Заголовок')) {
          cursorPosition = start + 3 // После "## "
        } else if (syntax.includes('### Заголовок')) {
          cursorPosition = start + 4 // После "### "
        } else if (syntax.includes('> Цитата')) {
          cursorPosition = start + 2 // После "> "
        } else if (syntax.includes('- Элемент списка')) {
          cursorPosition = start + 2 // После "- "
        } else if (syntax.includes('1. Элемент списка')) {
          cursorPosition = start + 3 // После "1. "
        } else {
          cursorPosition = start + insertedText.length
        }
      }

      const newValue =
        markdownContent.substring(0, start) +
        insertedText +
        markdownContent.substring(end)
      handleContentChange(newValue)

      // Возвращаем фокус в textarea
      setTimeout(() => {
        textarea.focus()
        if (!selectedText && syntax.includes('[текст](url)')) {
          // Для ссылок выделяем "текст"
          textarea.setSelectionRange(start + 1, start + 6)
        } else if (
          !selectedText &&
          (syntax.includes('**текст**') ||
            syntax.includes('*текст*') ||
            syntax.includes('~~текст~~') ||
            syntax.includes('`код`'))
        ) {
          // Для форматирования выделяем placeholder
          const placeholderStart =
            syntax.indexOf('текст') !== -1
              ? insertedText.indexOf('текст') + start
              : insertedText.indexOf('код') + start
          const placeholderLength = syntax.includes('код') ? 3 : 5
          textarea.setSelectionRange(
            placeholderStart,
            placeholderStart + placeholderLength
          )
        } else {
          textarea.setSelectionRange(cursorPosition, cursorPosition)
        }
      }, 0)
    }

    return (
      <div className="space-y-4">
        <div>
          <Label htmlFor="content" className="text-sm font-medium">
            Markdown содержимое
          </Label>
          <div className="mt-1 overflow-hidden rounded-md border border-gray-200">
            <MarkdownToolbar onInsert={insertText} />
            <Textarea
              data-markdown-editor
              value={markdownContent}
              onChange={e => handleContentChange(e.target.value)}
              placeholder="Введите markdown текст..."
              className="resize-none rounded-none border-0 font-mono text-sm focus:ring-0"
              style={{ minHeight: 300 }}
            />
          </div>
        </div>
      </div>
    )
  },
  Preview: ({ config }) => {
    return (
      <div className="space-y-2">
        {config.name && (
          <Label className="text-sm font-medium text-gray-900">
            {config.name}
          </Label>
        )}

        <MarkdownPreview
          content={config.content || '*Содержимое будет отображено здесь...*'}
        />
      </div>
    )
  },
  Render: ({ config, value, onChange }) => {
    return (
      <div className="relative space-y-2">
        {/* Бейдж ячеек в правом верхнем углу */}
        <div className="absolute right-0 top-0 z-10 flex items-center gap-1">
          <CellsBadge targetCells={config.targetCells} className="" />
        </div>

        {/* Лейбл поля */}
        {config.name && (
          <Label className="text-sm font-medium text-gray-900">
            {config.name}
          </Label>
        )}

        {/* Отображение markdown содержимого */}
        <MarkdownPreview
          content={config.content || value || '*Содержимое не задано...*'}
        />
      </div>
    )
  },
}
