import { buttonGroupDefinition } from '@/entity/element/model/implementations/ButtonGroup'
import { noteDefinition } from '@/entity/element/model/implementations/NoteElement'
import { selectDefinition } from '@/entity/element/model/implementations/SelectElement'
import { standardsDefinition } from '@/entity/element/model/implementations/StandardsElement/definition'
import { textDefinition } from '@/entity/element/model/implementations/TextElement'
import { verificationConditionsElementDefinition as verificationConditionsDefinition } from '@/entity/element/model/implementations/VerificationConditionsElement/definition'
import { CellTarget } from '@/type/template'
import { ReactNode } from 'react'

export interface ElementDefinition<Config = any, Value = any> {
  type: ElementType
  label: string
  icon: ReactNode

  /* React-компоненты */
  Editor: React.FC<{ config: Config; onChange(c: Config): void }>
  Preview: React.FC<{ config: Config }>
  Render: React.FC<{ config: Config; value: Value; onChange?(v: Value): void }>

  /* бизнес-логика */
  defaultConfig: Config
  getInitialValue?(config: Config): Value // получение начальных значений из конфигурации
  mapToCells(config: Config): CellTarget[] // куда пишем данные (для отображения)
  mapToCellValues(
    config: Config,
    value: Value
  ): Array<{ target: CellTarget; value: any }> // готовые пары ячейка-значение для записи

  /* мета */
  version: number
}

export const elementRegistry: Record<ElementType, ElementDefinition> = {} as any

// Функция для регистрации элемента
export function registerElement<T extends ElementType>(
  type: T,
  definition: ElementDefinition
) {
  elementRegistry[type] = definition
}

// Получить все доступные типы элементов
export function getAvailableElementTypes(): Array<{
  type: ElementType
  label: string
  icon: ReactNode
}> {
  return Object.values(elementRegistry).map(({ type, label, icon }) => ({
    type,
    label,
    icon,
  }))
}

// Получить определение элемента по типу
export function getElementDefinition(
  type: ElementType
): ElementDefinition | undefined {
  return elementRegistry[type]
}

export const elementDefinitions = {
  text: textDefinition,
  select: selectDefinition,
  note: noteDefinition,
  standards: standardsDefinition,
  verification_conditions: verificationConditionsDefinition,
  button_group: buttonGroupDefinition,
} as const

export type ElementType = keyof typeof elementDefinitions

export function initializeElementRegistry() {
  registerElement('text', textDefinition)
  registerElement('select', selectDefinition)
  registerElement('note', noteDefinition)
  registerElement('button_group', buttonGroupDefinition)
  registerElement('standards', standardsDefinition)
  registerElement('verification_conditions', verificationConditionsDefinition)
}
