import { Button } from '@citric/core'
import { useCallback, useMemo, useRef, useState } from 'react'
import { FieldRenderer } from '..'
import { JinjaRawContext, useJinjaContext } from '../../context/JinjaContext'
import { JinjaContextValue } from '../../context/JinjaContextValue'
import { buildFields } from '../../form/field-builder'
import { FormContextValue } from '../../form/FormContextValue'
import { FieldComponent, FieldConfig, FieldListConfig } from '../../form/types'

interface ContextInit {
  name: string,
  model: FieldConfig<Record<string, any>>,
  parent: JinjaContextValue,
  value?: any,
  onChange: () => void,
  onDestroy: (() => void)[],
}

function getFirstVariableOfContext(context: FormContextValue) {
  const keys = Object.keys(context.variables)
  const variables = context.variables[keys[0]]
  return variables[0]
}

function createFormContextValue({ name, value, model, onChange, parent, onDestroy }: ContextInit) {
  const ctx = new FormContextValue(name, [{ ...model, label: undefined, default: value }], parent as any)
  onDestroy.push(getFirstVariableOfContext(ctx).onChange(onChange))
  return ctx
}

function createFormContextsFromValue({ value, ...other }: ContextInit) {
  return Array.isArray(value)
    ? value.map(v => createFormContextValue({ value: v, ...other }))
    : [createFormContextValue(other)]
}

export const ObjectListField: FieldComponent<any[], Record<string, never>> = ({ name, value, onChange, variable }) => {
  const parent = useJinjaContext()
  const model = (variable.config as FieldListConfig).model
  const onDestroy = useRef<(() => void)[]>([])
  const [_, forceUpdate] = useState(Math.random())

  const handleAnyChange = useCallback(() => {
    onChange(items.current.map(ctx => getFirstVariableOfContext(ctx).get()))
  }, [])

  const items = useRef(createFormContextsFromValue(
    { value, name, model, parent: parent as any, onDestroy: onDestroy.current, onChange: handleAnyChange },
  ))
  const rendered = useMemo(() => items.current.map((item, index) => {
    const fields = buildFields(item.variables)
    return (
      <JinjaRawContext key={index} value={item as any}>
        <FieldRenderer Component={fields[0]} input={model.metadata} />
        <Button onClick={() => removeItem(index)}>Remover</Button>
      </JinjaRawContext>
    )
  }), [items.current])

  function addItem() {
    items.current = ([...items.current, createFormContextValue(
      { name, model, onChange: handleAnyChange, onDestroy: onDestroy.current, parent: parent as any },
    )])
    forceUpdate(Math.random())
    handleAnyChange()
  }

  function removeItem(index: number) {
    items.current = items.current.filter((_, i) => i !== index)
    forceUpdate(Math.random())
    handleAnyChange()
  }

  return (
    <div className="dynamic-list">
      {rendered}
      <Button onClick={addItem}>Adicionar</Button>
    </div>
  )  
}
