import DualSpreadsheet from '@/component/DualSpreadsheet/DualSpreadsheet'
import { getElementDefinition } from '@/entity/element/model/interface'
import { useTemplateContext } from '@/entity/template/model/TemplateContext'
import { useSafeNavigation } from '@/hook/useSafeNavigation'
import { cellAddressToCoordinates } from '@/lib/cell-utils'
import { useToast } from '@/lib/hooks/useToast'
import { getLatestFileForTemplate } from '@/service/fileApiService'
import { Template, TemplateElement } from '@/type/template'
import {
  ArrowLeft,
  FileText,
  Loader2,
  Save,
  Settings,
  Wrench,
} from 'lucide-react'
import { FC, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { Button } from 'shared/ui/button'

interface ProtocolFormProps {
  template: Template
  onSave: (data: Record<string, any>) => void
  onBack: () => void
}

const ProtocolForm: FC<ProtocolFormProps> = ({ template, onSave, onBack }) => {
  const [formData, setFormData] = useState<Record<string, any>>({})
  const [showSpreadsheet, setShowSpreadsheet] = useState(false)
  const [isInitialized, setIsInitialized] = useState(false)
  const [isSavingProtocol, setIsSavingProtocol] = useState(false)
  // Track spreadsheet engine readiness so initial form data syncs once it mounts
  const [isEngineReady, setIsEngineReady] = useState(false)
  const engineRef = useRef<any>(null)
  const toast = useToast()
  const navigate = useNavigate()

  // Хук для безопасной навигации (здесь нет автосохранения формы, только состояние)
  const { safeNavigate, isNavigating } = useSafeNavigation({
    hasUnsavedChanges: false, // Форма протокола не требует автосохранения
    isSaving: isSavingProtocol,
  })

  // Инициализация начальных значений формы (только один раз)
  useEffect(() => {
    if (!isInitialized && template.elements.length > 0) {
      const initialData: Record<string, any> = {}
      template.elements.forEach(element => {
        const elementDefinition = getElementDefinition(element.type)
        if (elementDefinition?.getInitialValue) {
          const initialValue = elementDefinition.getInitialValue(element as any)
          if (initialValue !== undefined && initialValue !== '') {
            initialData[element.id] = initialValue
          }
        }
      })
      console.log(initialData)

      if (Object.keys(initialData).length > 0) {
        setFormData(initialData)
      }

      setIsInitialized(true)
    }
  }, [template.elements, isInitialized])

  // Универальная функция синхронизации всех данных формы с движком
  const syncFormDataToEngine = () => {
    if (!engineRef.current) return

    console.log('Синхронизация всех данных формы с движком:', formData)

    template.elements.forEach(element => {
      const value = formData[element.id]
      if (value !== undefined) {
        const elementDefinition = getElementDefinition(element.type)
        if (elementDefinition) {
          const cellValues = elementDefinition.mapToCellValues(
            element as any,
            value
          )
          cellValues.forEach(({ target, value: cellValue }) => {
            const { row, col } = cellAddressToCoordinates(target.cell)
            engineRef.current.setCellValueWithoutRecalc(
              target.sheet,
              row,
              col,
              cellValue
            )
          })
        }
      }
    })

    engineRef.current.debouncedRecalc()
    // Принудительно обновляем UI для отображения изменений
    engineRef.current.updateRevision()
  }

  // Синхронизация с движком только когда он готов и есть данные
  useEffect(() => {
    if (
      isInitialized &&
      engineRef.current &&
      Object.keys(formData).length > 0
    ) {
      syncFormDataToEngine()
    }
  }, [isInitialized, formData, template.elements, isEngineReady])

  const handleFieldChange = (elementId: string, value: any) => {
    // Обновляем только состояние формы
    setFormData(prev => ({
      ...prev,
      [elementId]: value,
    }))
  }

  const handleSave = async () => {
    const data = {
      templateId: template.id,
      formData,
      createdAt: new Date(),
    }
    onSave(data)

    try {
      setIsSavingProtocol(true)

      if (!engineRef.current) {
        toast.error('Движок ещё не инициализирован')
        return
      }

      // Убеждаемся что все данные записаны в движок перед сохранением
      syncFormDataToEngine()

      // Небольшая задержка чтобы пересчёт завершился
      await new Promise(resolve => setTimeout(resolve, 100))

      // Получаем изменения только левого листа относительно базового файла
      const allModified = engineRef.current?.getAllModifiedCells() || {}
      const cellsToUpdate: Record<string, any> = {}
      const modifiedLeft = allModified['L'] || {}
      Object.keys(modifiedLeft).forEach(cellAddress => {
        const { row, col } = cellAddressToCoordinates(cellAddress)
        cellsToUpdate[cellAddress] = engineRef.current.getCellValue(
          'L',
          row,
          col
        )
      })

      // Получаем последний файл для шаблона
      const latestFile = await getLatestFileForTemplate(template.id)
      if (!latestFile) {
        toast.error('Не найден исходный файл Excel для шаблона')
        return
      }

      // Получаем значение print_area из ячейки R!A2
      const printAreaFromCell = engineRef.current.getCellValue('R', 1, 0) // R!A2

      const body = {
        cells_to_update: cellsToUpdate,
        file_id: latestFile.id,
        template_id: template.id,
        print_area: printAreaFromCell || '',
      }
      console.log('body', body)

      const resp = await fetch('/api/protocols/', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })

      if (!resp.ok) throw new Error(`HTTP ${resp.status}`)

      // Получаем файл как blob и скачиваем его
      const blob = await resp.blob()
      const url = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url

      // Получаем значение из ячейки R!A1 для имени файла
      const filenameFromCell = engineRef.current.getCellValue('R', 0, 0) // R!A1
      let filename = 'Измените R!A1.xlsx'

      if (
        filenameFromCell &&
        typeof filenameFromCell === 'string' &&
        filenameFromCell.trim()
      ) {
        const cleanName = filenameFromCell.trim().replace(/[<>:"/\\|?*]/g, '_')
        filename = `${cleanName}.xlsx`
      }

      const contentDisposition = resp.headers.get('content-disposition')
      if (contentDisposition) {
        if (!filenameFromCell || !filenameFromCell.toString().trim()) {
          const matches = contentDisposition.match(
            /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
          )
          if (matches && matches[1]) {
            filename = matches[1].replace(/['"]/g, '')
          }
        }
      }

      a.download = filename
      document.body.appendChild(a)
      a.click()
      window.URL.revokeObjectURL(url)
      document.body.removeChild(a)

      toast.success('Протокол создан и загружен!')
    } catch (err) {
      console.error('Ошибка при создании протокола', err)
      toast.error('Ошибка при создании протокола')
    } finally {
      setIsSavingProtocol(false)
    }
  }

  const canvasSize = useMemo(() => {
    const baseWidth = 1200

    if (template.elements.length === 0) {
      return { width: baseWidth, height: 150 } // Совсем маленькая высота для пустых
    }

    if (template.elements.length <= 2) {
      // Для малого количества элементов - минимальные отступы
      const contentHeight = Math.max(
        0,
        ...template.elements.map(
          el => (el.layout?.y || 0) + (el.layout?.height || 0)
        )
      )
      return {
        width: baseWidth,
        height: Math.max(200, contentHeight + 30), // Очень маленькие отступы
      }
    }

    // Для большого количества элементов - обычные отступы
    const contentHeight = Math.max(
      0,
      ...template.elements.map(
        el => (el.layout?.y || 0) + (el.layout?.height || 0)
      )
    )

    return {
      width: baseWidth,
      height: Math.max(300, contentHeight + 80),
    }
  }, [template.elements])

  const canSave = true

  return (
    <div className="flex h-screen flex-col bg-background">
      <div className="flex-shrink-0 bg-card px-4 py-2">
        <div className="relative flex items-center">
          {/* Левая часть: кнопка назад и заголовок */}
          <div className="flex items-center gap-2">
            <Button
              variant="ghost"
              size="icon"
              onClick={onBack}
              disabled={isNavigating || isSavingProtocol}
            >
              {isNavigating ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <ArrowLeft className="h-4 w-4" />
              )}
            </Button>
            <div className="flex items-center space-x-2">
              <FileText className="h-5 w-5" />
              <h1 className="text-lg font-semibold">Создание протокола</h1>
              <span className="text-sm text-muted-foreground">—</span>
              <span className="text-sm text-muted-foreground">
                {template.name}
              </span>
            </div>
          </div>
          {/* Центрированные кнопки */}
          <div className="absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 gap-2">
            <Button
              variant="outline"
              onClick={handleSave}
              disabled={!canSave || isSavingProtocol}
            >
              {isSavingProtocol ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  Сохранение...
                </>
              ) : (
                <>
                  <Save className="h-4 w-4" />
                  Сохранить протокол
                </>
              )}
            </Button>
          </div>
          {/* Кнопки справа */}
          <div className="absolute right-0 flex gap-2">
            <Button
              variant="link"
              size="sm"
              onClick={() => safeNavigate(`/templates/${template.id}/edit`)}
              disabled={isNavigating || isSavingProtocol}
              className="flex items-center gap-1 hover:bg-muted"
            >
              {isNavigating ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span className="text-sm">Переход...</span>
                </>
              ) : (
                <>
                  <Settings className="h-4 w-4" />
                  <span className="text-sm">Редактор шаблона</span>
                </>
              )}
            </Button>
            <Button
              variant="link"
              size="sm"
              onClick={() => safeNavigate(`/templates/${template.id}/elements`)}
              disabled={isNavigating || isSavingProtocol}
              className="flex items-center gap-1 hover:bg-muted"
            >
              {isNavigating ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span className="text-sm">Переход...</span>
                </>
              ) : (
                <>
                  <Wrench className="h-4 w-4" />
                  <span className="text-sm">Редактор интерфейса</span>
                </>
              )}
            </Button>
          </div>
        </div>
      </div>

      {/* Основное содержимое */}
      <div className="flex-1 overflow-hidden">
        <div className={`${showSpreadsheet ? 'block' : 'hidden'} h-full`}>
          <DualSpreadsheet
            templateData={template.excelData ? { L: template.excelData } : {}}
            mergedCells={template.mergedCells || []}
            templateId={template.id}
            onEngineReady={engine => {
              engineRef.current = engine
              if (!isEngineReady) {
                setIsEngineReady(true)
              }

              // Immediately push any captured form data into the engine after it appears
              if (
                isInitialized &&
                Object.keys(formData).length > 0
              ) {
                syncFormDataToEngine()
              }
            }}
          />
        </div>

        {/* Форма */}
        <div
          className={`${showSpreadsheet ? 'hidden' : 'block'} h-full overflow-auto`}
        >
          <div
            className="relative mx-auto my-2"
            style={{ width: canvasSize.width, height: canvasSize.height }}
          >
            {template.elements.map(element => {
              const layout = element.layout || {
                x: 50,
                y: 50,
                width: 300,
                height: 80,
              }
              return (
                <div
                  key={element.id}
                  className="absolute"
                  style={{
                    left: layout.x,
                    top: layout.y,
                    width: layout.width,
                    minHeight: layout.height,
                    zIndex: layout.zIndex || 1,
                  }}
                >
                  <FormElement
                    element={element}
                    value={formData[element.id]}
                    onChange={value => handleFieldChange(element.id, value)}
                  />
                </div>
              )
            })}

            {template.elements.length === 0 && (
              <div className="absolute inset-0 flex items-center justify-center">
                <div className="text-center text-gray-400">
                  {/* <FileText className="mx-auto mb-4 h-16 w-16" /> */}
                  <h3 className="mb-2 text-lg font-medium text-gray-900">
                    Нет интерфейса
                  </h3>
                  <p className="mb-4 text-gray-600">
                    В этом шаблоне пока не созданы элементы интерфейса
                  </p>
                  <Button
                    variant="outline"
                    onClick={() => safeNavigate(`/templates/${template.id}/edit`)}
                  >
                    Настроить шаблон
                  </Button>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  )
}

export const ProtocolCreation: FC = () => {
  const navigate = useNavigate()
  const { templateId } = useParams<{ templateId?: string }>()
  const { templates } = useTemplateContext()
  const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(
    null
  )
  const toast = useToast()
  // Автоматически выбираем шаблон если передан ID в URL
  useEffect(() => {
    if (templateId && templates.length > 0) {
      const template = templates.find(t => t.id === templateId)
      if (template) {
        setSelectedTemplate(template)
      }
    }
  }, [templateId, templates])

  if (!selectedTemplate) {
    return (
      <div className="flex h-screen items-center justify-center">
        <div className="text-center">
          <FileText className="mx-auto mb-4 h-16 w-16 text-gray-400" />
          <h3 className="mb-2 text-lg font-medium text-gray-900">
            Шаблон не найден
          </h3>
          <p className="mb-4 text-gray-600">
            Перейдите к списку шаблонов для выбора
          </p>
          <Button onClick={() => navigate('/templates')}>
            К списку шаблонов
          </Button>
        </div>
      </div>
    )
  }

  return (
    <ProtocolForm
      template={selectedTemplate}
      onSave={() => {
        toast.info(`Подождите, Excel файл создаётся...`)
      }}
      onBack={() => {
        navigate('/templates')
      }}
    />
  )
}

interface FormElementProps {
  element: TemplateElement
  value: any
  onChange: (value: any) => void
}

const FormElement: FC<FormElementProps> = ({ element, value, onChange }) => {
  const elementDefinition = getElementDefinition(element.type)
  if (!elementDefinition) {
    return (
      <div className="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-700">
        Элемент типа "{element.type}" не найден в реестре
      </div>
    )
  }

  const renderElement = () => (
    <elementDefinition.Render
      config={element as any}
      value={value}
      onChange={onChange}
    />
  )

  return <div className="relative space-y-3">{renderElement()}</div>
}
