import {
  createContext,
  Dispatch,
  ReactNode,
  SetStateAction,
  useContext,
  useMemo,
  useState,
} from 'react'
import { useForm, UseFormProps } from './useForm.js'
import { FormFieldProps } from './FormField.js'
import { SelectInputProps } from '../SelectInput/index.js'
import { FormValues } from './types.js'
import { FormFields as FormFieldsComponent } from './FormFields.js'
import { FormTabs } from './FormTabs.js'
import { TextInputProps } from '../TextInput/index.js'
import { EnumTagInputProps, TagInputProps } from '../TagInput/index.js'
import { SchemaTypeName } from '@based/schema'
import { IconProps } from '../Icon/index.js'

const FormContext = createContext<{
  fields: FormFieldsType
  groups: FormProps['groups']
  form: ReturnType<typeof useForm>
  activeGroup?: string
  setActiveGroup: Dispatch<SetStateAction<string>>
  endpoints?: FormProps['endpoints']
  validate: UseFormProps['validate']
  onSubmit: UseFormProps['onSubmit']
} | null>(null)

type TextFormField = {
  type: 'text'
  inputType?: TextInputProps['type']
  placeholder?: string
  disabled?: boolean
}
type TextAreaFormField = {
  type: 'textarea'
  placeholder?: string
  disabled?: boolean
}
type NumberFormField = {
  type: 'number'
  placeholder?: string
  disabled?: boolean
}
type SwitchFormField = {
  type: 'switch'
  placeholder?: string
  disabled?: boolean
}
type CheckboxFormField = {
  type: 'checkbox'
  placeholder?: string
  disabled?: boolean
}
type DateFormField = { type: 'date'; placeholder?: string; disabled?: boolean }
type DateTimeFormField = {
  type: 'datetime'
  placeholder?: string
  disabled?: boolean
}
type SelectFormField = {
  type: 'select'
  placeholder?: string
  disabled?: boolean
} & Pick<SelectInputProps, 'options' | 'filterable'>
type RichTextFormField = {
  type: 'richtext'
  placeholder?: string
  disabled?: boolean
}
type ReferenceField = {
  type: 'reference'
  variant: 'single' | 'multiple'
  ref: SchemaTypeName
  placeholder?: string
  placeholderIcon?: IconProps['variant']
  disabled?: boolean
}
type TagField = {
  type: 'tag'
  variant: TagInputProps['variant']
  options?: EnumTagInputProps['options']
  placeholder?: string
  placeholderIcon?: IconProps['variant']
  disabled?: boolean
}
type FormFieldType = (
  | TextFormField
  | TextAreaFormField
  | NumberFormField
  | SwitchFormField
  | CheckboxFormField
  | DateFormField
  | DateTimeFormField
  | SelectFormField
  | RichTextFormField
  | ReferenceField
  | TagField
) &
  Pick<FormFieldProps, 'label' | 'description' | 'note'>
type FormFieldsType = {
  [key: string]: FormFieldType | FormFieldsType
}

type FormProps = {
  children: ReactNode | ((form: ReturnType<typeof useForm>) => React.ReactNode)
  groups?: {
    label: string
    description?: string
    fields: string[]
  }[]
  fields: FormFieldsType | ((values: FormValues) => FormFieldsType)
  endpoints?: {
    query?: string
    totalQuery?: string
    schema?: string
  }
} & UseFormProps

function Form({
  fields: fieldsProp,
  groups,
  children,
  endpoints,
  ...useFormProps
}: FormProps) {
  const [activeGroup, setActiveGroup] = useState<string>('__all')
  const form = useForm(useFormProps)
  const fields =
    typeof fieldsProp === 'function' ? fieldsProp(form.values) : fieldsProp

  return (
    <FormContext.Provider
      value={{
        fields,
        form,
        groups,
        activeGroup,
        setActiveGroup,
        endpoints,
        validate: useFormProps.validate,
        onSubmit: useFormProps.onSubmit,
      }}
    >
      {typeof children === 'function' ? children(form) : children}
    </FormContext.Provider>
  )
}

Form.Fields = FormFieldsComponent
Form.Tabs = FormTabs

export { Form, FormContext }
export type { FormProps, FormFieldsType, FormFieldType }
