import {
  getAvailableElementTypes,
  getElementDefinition,
} from '@/entity/element/model/interface'
import { useToast } from '@/lib/hooks/useToast'
import { generateDefaultLayout } from '@/lib/utils'
import {
  CellTarget,
  ElementType,
  FormLayoutSettings,
  Template,
  TemplateElement,
} from '@/type/template'
import {
  AlertTriangle,
  Eye,
  HelpCircle,
  Plus,
  Settings2,
  Tag,
  Target,
  Trash2,
  Type,
} from 'lucide-react'
import React, { useState } from 'react'
import { Button } from 'shared/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from 'shared/ui/card'
import { Checkbox } from 'shared/ui/checkbox'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from 'shared/ui/dialog'
import { Input } from 'shared/ui/input'
import { Label } from 'shared/ui/label'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from 'shared/ui/select'
import { Separator } from 'shared/ui/separator'
import { v4 as uuidv4 } from 'uuid'
import { ElementFormulaBar } from './ElementFormulaBar'
import { VisualLayoutEditor } from './VisualLayoutEditor'

export function getDefaultLayoutSettings(): FormLayoutSettings {
  return {
    gridSize: 20,
    showGrid: true,
    snapToGrid: true,
  }
}

interface ElementFormProps {
  formData: Partial<TemplateElement>
  setFormData: React.Dispatch<React.SetStateAction<Partial<TemplateElement>>>
}

const CellTargetEditor: React.FC<{
  targets: CellTarget[]
  onChange: (targets: CellTarget[]) => void
}> = ({ targets, onChange }) => {
  const { warning } = useToast()

  const handleAddTarget = () => {
    onChange([...targets, { sheet: 'L', cell: '' }])
  }

  const handleUpdateTarget = (
    index: number,
    field: keyof CellTarget,
    value: string
  ) => {
    const updatedTargets = targets.map((target, i) =>
      i === index ? { ...target, [field]: value } : target
    )
    onChange(updatedTargets)
  }

  const handleRemoveTarget = (index: number) => {
    onChange(targets.filter((_, i) => i !== index))
  }

  const handleCellInputChange = (index: number, value: string) => {
    // Проверяем на наличие кириллицы
    const hasCyrillic = /[а-яё]/i.test(value)

    if (hasCyrillic) {
      warning('Кириллические символы не разрешены в адресе ячейки', {
        title: 'Недопустимый символ',
        duration: 3000,
      })
      return // Не обновляем значение
    }

    handleUpdateTarget(index, 'cell', value)
  }

  return (
    <Card>
      <CardHeader className="pb-2">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2">
            <Target className="h-4 w-4 text-blue-600" />
            <CardTitle className="text-sm">Целевые ячейки</CardTitle>
          </div>
          <Button
            variant="outline"
            size="sm"
            onClick={handleAddTarget}
            className="h-6 px-2 text-xs"
          >
            <Plus className="mr-1 h-3 w-3" />
            Добавить
          </Button>
        </div>
      </CardHeader>
      <CardContent className="pt-0">
        <div className="max-h-48 space-y-2 overflow-y-auto">
          {targets.map((target, index) => (
            <div
              key={index}
              className="flex items-center gap-2 rounded-lg border bg-gray-50/50 p-2"
            >
              {/* Кнопки выбора листа */}
              <div className="flex gap-1">
                <Button
                  variant={target.sheet === 'L' ? 'default' : 'outline'}
                  size="sm"
                  onClick={() => handleUpdateTarget(index, 'sheet', 'L')}
                  className="h-6 w-7 p-0 text-xs"
                >
                  L
                </Button>
                <Button
                  variant={target.sheet === 'R' ? 'default' : 'outline'}
                  size="sm"
                  onClick={() => handleUpdateTarget(index, 'sheet', 'R')}
                  className="h-6 w-7 p-0 text-xs"
                >
                  R
                </Button>
              </div>

              {/* Поле ввода ячейки */}
              <Input
                placeholder="A12"
                value={target.cell}
                onChange={e => handleCellInputChange(index, e.target.value)}
                className="h-6 w-16 px-2 text-xs"
              />

              {/* Кнопка удаления */}
              <Button
                variant="ghost"
                size="sm"
                onClick={() => handleRemoveTarget(index)}
                className="ml-auto h-6 w-6 p-0 text-red-600 hover:bg-red-50 hover:text-red-700"
              >
                <Trash2 className="h-3 w-3" />
              </Button>
            </div>
          ))}

          {targets.length === 0 && (
            <div className="py-4 text-center">
              <Target className="mx-auto mb-1 h-6 w-6 text-gray-300" />
              <p className="text-xs text-gray-500">
                Добавьте ячейки для связи с элементом
              </p>
              <p className="mt-1 text-xs text-gray-400">
                Например: A1, B5, C10
              </p>
            </div>
          )}
        </div>

        {targets.length > 0 && (
          <div className="mt-2 flex items-center gap-1 text-xs text-gray-500">
            <HelpCircle className="h-3 w-3" />
            Всего ячеек: {targets.length}
          </div>
        )}
      </CardContent>
    </Card>
  )
}

// Live Preview компонент
const ElementPreview: React.FC<{ element: Partial<TemplateElement> }> = ({
  element,
}) => {
  const elementDefinition = element.type
    ? getElementDefinition(element.type)
    : null

  return (
    <Card className="h-full">
      <CardHeader className="pb-3">
        <div className="flex items-center gap-2">
          <Eye className="h-4 w-4 text-green-600" />
          <CardTitle className="text-sm">Предпросмотр элемента</CardTitle>
        </div>
      </CardHeader>
      <CardContent className="pt-0">
        <div className="min-h-[200px] rounded-lg border border-gray-200 bg-white p-4">
          {elementDefinition && elementDefinition.Preview ? (
            <elementDefinition.Preview config={element as any} />
          ) : (
            <div className="space-y-3">
              {element.label && (
                <label className="mb-2 block text-sm font-medium text-gray-700">
                  {element.label}
                  {element.required && (
                    <span className="ml-1 text-red-500">*</span>
                  )}
                </label>
              )}

              <div className="flex items-center justify-center gap-2 rounded border border-gray-200 bg-gray-50 p-3 text-center text-sm text-gray-500">
                <AlertTriangle className="h-4 w-4" />
                {element.type
                  ? `Элемент типа "${element.type}" не найден`
                  : 'Выберите тип элемента'}
              </div>
            </div>
          )}
        </div>
      </CardContent>
    </Card>
  )
}

const ElementForm: React.FC<ElementFormProps> = ({ formData, setFormData }) => {
  const elementDefinition = formData.type
    ? getElementDefinition(formData.type)
    : null

  return (
    <div className="grid h-full grid-cols-1 gap-6 lg:grid-cols-2">
      {/* Настройки элемента */}
      <div className="max-h-[60vh] space-y-4 overflow-y-auto pr-2">
        {/* Основные настройки */}
        <Card>
          <CardHeader className="pb-3">
            <div className="flex items-center gap-2">
              <Settings2 className="h-4 w-4 text-blue-600" />
              <CardTitle className="text-sm">Основные настройки</CardTitle>
            </div>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="space-y-2">
              <Label className="flex items-center gap-2 text-sm font-medium">
                <Type className="h-3 w-3" />
                Тип элемента
              </Label>
              <Select
                value={formData.type}
                onValueChange={value => {
                  const newType = value as ElementType
                  const elementDefinition = getElementDefinition(newType)

                  setFormData(prev => {
                    const updates: Partial<TemplateElement> = {
                      type: newType,
                      targetCells: [],
                    }

                    if (elementDefinition && elementDefinition.defaultConfig) {
                      Object.assign(updates, elementDefinition.defaultConfig)
                    }

                    return { ...prev, ...updates }
                  })
                }}
              >
                <SelectTrigger className="h-9">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {getAvailableElementTypes().map(({ type, label, icon }) => (
                    <SelectItem key={type} value={type}>
                      <div className="flex items-center gap-2">
                        {icon}
                        {label}
                      </div>
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
              <div className="space-y-2">
                <Label className="flex items-center gap-2 text-sm font-medium">
                  <Tag className="h-3 w-3" />
                  Подпись
                </Label>
                <Input
                  placeholder="Название поля"
                  value={formData.label}
                  onChange={e =>
                    setFormData(prev => ({ ...prev, label: e.target.value }))
                  }
                  className="h-9"
                />
              </div>

              <div className="space-y-2">
                <Label className="flex items-center gap-2 text-sm font-medium">
                  <HelpCircle className="h-3 w-3" />
                  Подсказка
                </Label>
                <Input
                  placeholder="Введите значение..."
                  value={formData.placeholder}
                  onChange={e =>
                    setFormData(prev => ({
                      ...prev,
                      placeholder: e.target.value,
                    }))
                  }
                  className="h-9"
                />
              </div>
            </div>

            <div className="flex items-center space-x-2 py-1">
              <Checkbox
                id="required"
                checked={formData.required}
                onCheckedChange={checked =>
                  setFormData(prev => ({ ...prev, required: !!checked }))
                }
              />
              <Label htmlFor="required" className="text-sm font-medium">
                Обязательное поле
              </Label>
            </div>
          </CardContent>
        </Card>

        {/* Целевые ячейки */}
        <CellTargetEditor
          targets={formData.targetCells || []}
          onChange={targets =>
            setFormData(prev => ({ ...prev, targetCells: targets }))
          }
        />

        {/* Специфичный редактор элемента */}
        {elementDefinition && elementDefinition.Editor && (
          <Card>
            <CardHeader className="pb-3">
              <div className="flex items-center gap-2">
                <Settings2 className="h-4 w-4 text-purple-600" />
                <CardTitle className="text-sm">
                  Дополнительные настройки
                </CardTitle>
              </div>
            </CardHeader>
            <CardContent>
              <elementDefinition.Editor
                config={formData as any}
                onChange={newConfig =>
                  setFormData(prev => ({ ...prev, ...newConfig }))
                }
              />
            </CardContent>
          </Card>
        )}
      </div>

      {/* Предпросмотр */}
      <div className="h-fit lg:sticky lg:top-0">
        <ElementPreview element={formData} />
      </div>
    </div>
  )
}

interface CanvasSettingsProps {
  settings: FormLayoutSettings
  onChange: (settings: FormLayoutSettings) => void
}

const CanvasSettings: React.FC<CanvasSettingsProps> = ({
  settings,
  onChange,
}) => {
  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <label className="text-sm font-medium">Размер сетки (px)</label>
        <Select
          value={settings.gridSize.toString()}
          onValueChange={value =>
            onChange({ ...settings, gridSize: parseInt(value) })
          }
        >
          <SelectTrigger>
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="10">10px</SelectItem>
            <SelectItem value="20">20px</SelectItem>
            <SelectItem value="25">25px</SelectItem>
            <SelectItem value="50">50px</SelectItem>
          </SelectContent>
        </Select>
      </div>

      <div className="flex items-center space-x-2">
        <Checkbox
          id="showGrid"
          checked={settings.showGrid}
          onCheckedChange={checked =>
            onChange({ ...settings, showGrid: !!checked })
          }
        />
        <label htmlFor="showGrid" className="text-sm font-medium">
          Показывать сетку
        </label>
      </div>
    </div>
  )
}

interface ElementConstructorProps {
  template: Template
  onElementAdd: (element: TemplateElement) => void
  // Принимаем частичное обновление элемента, чтобы корректно обновлять только изменённые поля
  onElementUpdate: (
    elementId: string,
    updates: Partial<TemplateElement>
  ) => void
  onElementDelete: (elementId: string) => void
  disabled?: boolean
  // Пропсы для сохранения
  hasUnsavedChanges?: boolean
  isSaving?: boolean
  lastSaveError?: string | null
  onManualSave?: () => Promise<void>
  onClearError?: () => void
  // Пропсы для настроек макета
  onLayoutSettingsChange?: (settings: FormLayoutSettings) => void
}

export const ElementConstructor: React.FC<ElementConstructorProps> = ({
  template,
  onElementAdd,
  onElementUpdate,
  onElementDelete,
  disabled = false,
  hasUnsavedChanges = false,
  isSaving = false,
  lastSaveError = null,
  onManualSave,
  onClearError,
  onLayoutSettingsChange,
}) => {
  const elements = template.elements
  const layoutSettings = template.layoutSettings || getDefaultLayoutSettings()
  const [isAddDialogOpen, setIsAddDialogOpen] = useState(false)
  const [editingElement, setEditingElement] = useState<TemplateElement | null>(
    null
  )
  // Функция для создания дефолтной конфигурации
  const createDefaultFormData = (type: ElementType = 'text') => {
    const elementDefinition = getElementDefinition(type)

    const baseData = {
      type,
      name: '',
      label: '',
      targetCells: [],
      placeholder: '',
      required: false,
      options: [],
    }

    // Применяем defaultConfig если он есть
    if (elementDefinition && elementDefinition.defaultConfig) {
      Object.assign(baseData, elementDefinition.defaultConfig)
    }

    return baseData
  }

  const [formData, setFormData] = useState<Partial<TemplateElement>>(
    createDefaultFormData()
  )

  const resetForm = () => {
    setFormData(createDefaultFormData())
  }

  const handleAddElement = () => {
    if (!formData.label) {
      return
    }

    // Получаем определение элемента
    const elementDefinition = getElementDefinition(formData.type as ElementType)
    if (!elementDefinition) {
      console.error(`Element definition for ${formData.type} not found`)
      return
    }

    // Генерируем layout для нового элемента
    const defaultLayout = generateDefaultLayout(elements.length)

    // Используем targetCells из формы или генерируем через mapToCells
    let targetCells = formData.targetCells || []
    if (!targetCells.length) {
      targetCells = elementDefinition.mapToCells(formData as any) || []
    }

    const newElement: TemplateElement = {
      ...formData, // Копируем все поля из formData, включая специфичные для элемента
      id: uuidv4(),
      type: formData.type as ElementType,
      name: formData.label || '',
      label: formData.label,
      targetCells,
      placeholder: formData.placeholder,
      required: formData.required,
      options: formData.options,
      order: elements.length,
      layout: defaultLayout,
    } as TemplateElement

    onElementAdd(newElement)
    resetForm()
    setIsAddDialogOpen(false)
  }

  const handleEditElement = (element: TemplateElement) => {
    setEditingElement(element)
    setFormData(element)
  }

  const handleUpdateElement = () => {
    if (!editingElement || !formData.label) return

    // Получаем определение элемента
    const elementDefinition = getElementDefinition(
      editingElement.type as ElementType
    )
    if (!elementDefinition) {
      console.error(`Element definition for ${editingElement.type} not found`)
      return
    }

    // Используем targetCells из формы или генерируем через mapToCells
    let targetCells = formData.targetCells || []
    if (!targetCells.length) {
      targetCells = elementDefinition.mapToCells(formData as any) || []
    }

    const updatedData = {
      ...formData,
      name: formData.label || formData.name || '',
      targetCells,
    }

    onElementUpdate(editingElement.id, updatedData)
    setEditingElement(null)
    resetForm()
  }

  const handleCancelEdit = () => {
    setEditingElement(null)
    resetForm()
  }

  const handleDeleteAndSelect = (elementId: string) => {
    onElementDelete(elementId)
    setEditingElement(null)
    resetForm()
  }

  const handleElementCopy = (element: Omit<TemplateElement, 'id'>) => {
    const newElement: TemplateElement = {
      ...element,
      id: Date.now().toString(),
      order: elements.length,
    }
    onElementAdd(newElement)
  }

  return (
    <div className="flex h-full w-full flex-col bg-background">
      <ElementFormulaBar
        elementCount={elements.length}
        onAddElement={() => setIsAddDialogOpen(true)}
        disabled={disabled}
        hasUnsavedChanges={hasUnsavedChanges}
        isSaving={isSaving}
        lastSaveError={lastSaveError}
        onManualSave={onManualSave}
        onClearError={onClearError}
        showGrid={layoutSettings.showGrid}
        onToggleGrid={
          onLayoutSettingsChange
            ? () => {
                const newSettings = {
                  ...layoutSettings,
                  showGrid: !layoutSettings.showGrid,
                }
                onLayoutSettingsChange(newSettings)
              }
            : undefined
        }
        snapToGrid={layoutSettings.snapToGrid}
        onToggleSnapToGrid={
          onLayoutSettingsChange
            ? () => {
                const newSettings = {
                  ...layoutSettings,
                  snapToGrid: !layoutSettings.snapToGrid,
                }
                onLayoutSettingsChange(newSettings)
              }
            : undefined
        }
      />

      <div className="flex-1 overflow-hidden">
        <VisualLayoutEditor
          elements={elements}
          layoutSettings={layoutSettings}
          onElementUpdate={onElementUpdate}
          onElementDelete={handleDeleteAndSelect}
          onLayoutSettingsChange={onLayoutSettingsChange || (() => {})}
          onElementEdit={handleEditElement}
          onElementAdd={handleElementCopy}
          isDialogOpen={isAddDialogOpen || !!editingElement}
        />
      </div>

      {/* Диалог добавления элемента */}
      <Dialog open={isAddDialogOpen} onOpenChange={setIsAddDialogOpen}>
        <DialogContent className="max-h-[90vh] max-w-6xl overflow-hidden">
          <DialogHeader className="pb-4">
            <DialogTitle className="flex items-center gap-2 text-lg">
              <Plus className="h-5 w-5 text-blue-600" />
              Добавить новый элемент
            </DialogTitle>
            <DialogDescription>
              Создайте и настройте новый элемент формы. Вы можете увидеть
              предпросмотр справа.
            </DialogDescription>
          </DialogHeader>
          <div className="flex-1 overflow-hidden">
            <ElementForm formData={formData} setFormData={setFormData} />
          </div>
          <Separator className="my-4" />
          <div className="flex items-center justify-between pt-2">
            <div className="text-sm text-gray-500">
              {!formData.label && (
                <div className="flex items-center gap-1 text-amber-600">
                  <AlertTriangle className="h-3 w-3" />
                  Заполните обязательные поля
                </div>
              )}
            </div>
            <div className="flex gap-3">
              <Button
                onClick={() => setIsAddDialogOpen(false)}
                variant="outline"
              >
                Отмена
              </Button>
              <Button
                onClick={handleAddElement}
                disabled={disabled || !formData.label}
                className="min-w-[140px]"
              >
                <Plus className="mr-2 h-4 w-4" />
                Добавить элемент
              </Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      {/* Диалог редактирования элемента */}
      {editingElement && (
        <Dialog open={!!editingElement} onOpenChange={() => handleCancelEdit()}>
          <DialogContent className="max-h-[90vh] max-w-6xl overflow-hidden">
            <DialogHeader className="pb-4">
              <DialogTitle className="flex items-center gap-2 text-lg">
                <Settings2 className="h-5 w-5 text-green-600" />
                Редактировать элемент
              </DialogTitle>
              <DialogDescription>
                Измените параметры элемента "
                {editingElement.label || editingElement.name}".
              </DialogDescription>
            </DialogHeader>
            <div className="flex-1 overflow-hidden">
              <ElementForm formData={formData} setFormData={setFormData} />
            </div>
            <Separator className="my-4" />
            <div className="flex items-center justify-between pt-2">
              <div className="text-sm text-gray-500">
                {!formData.label && (
                  <div className="flex items-center gap-1 text-amber-600">
                    <AlertTriangle className="h-3 w-3" />
                    Заполните обязательные поля
                  </div>
                )}
              </div>
              <div className="flex gap-3">
                <Button onClick={handleCancelEdit} variant="outline">
                  Отмена
                </Button>
                <Button
                  onClick={handleUpdateElement}
                  disabled={disabled || !formData.label}
                  className="min-w-[160px]"
                >
                  <Settings2 className="mr-2 h-4 w-4" />
                  Сохранить изменения
                </Button>
              </div>
            </div>
          </DialogContent>
        </Dialog>
      )}
    </div>
  )
}
