/* eslint-disable @typescript-eslint/no-explicit-any */
import {
  Checkbox,
  Chip,
  ColorInput,
  FileInput,
  JsonInput,
  MultiSelect,
  NumberInput,
  PasswordInput,
  PinInput,
  Radio,
  RadioGroup,
  Rating,
  Select,
  Switch,
  TagsInput,
  TextInput,
  Textarea,
} from '@mantine/core'
import { DateInput, DateTimePicker } from '@mantine/dates'
import classes from './RenderForm.module.css'
type TItem = {
  key: string
  name: string
  type: string
  optional?: any
  status?: boolean
  data?: any
  customOnChange?: (e: any, form: any, item: TItem) => void
}

const RenderInput = ({
  formFormat,
  form,
  column,
}: {
  formFormat: TItem[]
  form: any
  column: number
}) => {
  const style = {
    width: column > 1 ? 'calc(100%/' + column + ' - 10px)' : '100%',
  }

  return (
    <>
      {formFormat.map((item) => {
        switch (item.type) {
          case 'TagsInput':
            return (
              <TagsInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'MultiSelect':
            return (
              <MultiSelect
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'Textarea':
            return (
              <Textarea
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.target.value)
                }}
                data={item.data}
              />
            )
          case 'Switch':
            return (
              <Switch
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                checked={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.currentTarget.checked)
                }}
                data={item.data}
              />
            )
          case 'Rating':
            return (
              <Rating
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'Radio':
            return (
              <Radio
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                checked={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.currentTarget.checked)
                }}
                data={item.data}
              />
            )
          case 'PinInput':
            return (
              <PinInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'PasswordInput':
            return (
              <PasswordInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.target.value)
                }}
                data={item.data}
              />
            )
          case 'NumberInput':
            return (
              <NumberInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'JsonInput':
            return (
              <JsonInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'FileInput':
            return (
              <FileInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'TextInput':
            return (
              <TextInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.target.value)
                }}
              />
            )
          case 'RadioGroup':
            return (
              <RadioGroup
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                style={style}
                error={form.errors[item.key]}
                value={form.values[item.key]}
                label={item.name}
                onDoubleClick={() => {
                  form.setFieldValue(item.key, '')
                }}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
              >
                {item.data}
              </RadioGroup>
            )
          case 'DateTimePicker':
            return (
              <DateTimePicker
                {...(item.optional ? item.optional(form) : {})}
                value={
                  form.values[item.key]
                    ? form.values[item.key] !== null &&
                      form.values[item.key].length === 10
                      ? new Date(form.values[item.key] * 1000)
                      : form.values[item.key]
                    : ''
                }
                clearable
                key={item.key}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
              />
            )
          case 'DateInput':
            return (
              <DateInput
                {...(item.optional ? item.optional(form) : {})}
                value={
                  form.values[item.key]
                    ? form.values[item.key] !== null &&
                      form.values[item.key].length === 10
                      ? new Date(form.values[item.key] * 1000)
                      : form.values[item.key]
                    : ''
                }
                clearable
                valueFormat="YYYY/MM/DD"
                key={item.key}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
              />
            )
          case 'Select':
            return (
              <Select
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
          case 'Checkbox':
            return (
              <Checkbox
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                checked={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e.target.checked)
                }}
                data={item.data}
              />
            )
          case 'Chip':
            return (
              <Chip
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                checked={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
              >
                {item.data}
              </Chip>
            )
          case 'ColorInput':
            return (
              <ColorInput
                {...(item.optional ? item.optional(form) : {})}
                key={item.key}
                value={form.values[item.key]}
                style={style}
                error={form.errors[item.key]}
                label={item.name}
                onChange={(e) => {
                  item.customOnChange
                    ? item.customOnChange(e, form, item)
                    : form.setFieldValue(item.key, e)
                }}
                data={item.data}
              />
            )
        }
      })}
    </>
  )
}

/**
 * @author Joseph Le
 * @param formFormat (Array)
 * ``` 
    type TItem = {
    key: string // Name of input
    name: string // Label of input
    type: string 
    optional?: any // Any prop of tag input
    status?: boolean
    data?: any // Used for input with custom data or need to place content in the middle of the tag
    customOnChange?: (e: any) => void // Default is set new value
    }
```
 ****type: ([Checkbox](https://mantine.dev/core/checkbox/), [Chip](https://mantine.dev/core/chip/), [ColorInput](https://mantine.dev/core/color-input/), [FileInput](https://mantine.dev/core/file-input/), [JsonInput](https://mantine.dev/core/json-input/), [NumberInput](https://mantine.dev/core/number-input/), [PasswordInput](https://mantine.dev/core/password-input/), [PinInput](https://mantine.dev/core/pin-input/), [Radio](https://mantine.dev/core/radio/), [Rating](https://mantine.dev/core/rating/), [Switch](https://mantine.dev/core/switch/), [Textarea](https://mantine.dev/core/textarea/), [TextInput](https://mantine.dev/core/text-input/), [MultiSelect](https://mantine.dev/core/multi-select/), [Select](https://mantine.dev/core/select/), [TagsInput](https://mantine.dev/core/tags-input/), [RadioGroup](https://v2.mantine.dev/core/radio-group/), [DateTimePicker](https://mantine.dev/dates/date-time-picker/), [DateInput](https://mantine.dev/dates/date-input/))
 *  
 * @param values (From)

 ```
 Example:
    const form = useForm<Type>({
        initialValues: {},
        validate: (values) => ({
        email: values.email === '' ? 'Email is required' : /^\S+@\S+$/.test(values.email) ? null : 'Invalid email'
        ...
        })
    })
 ```
 * @param column (Integer) Used for set layout input
 */

const RenderForm = ({
  formFormat,
  form,
  column,
}: {
  formFormat: TItem[]
  form: any
  column: number
}) => {
  return (
    <div className={classes.formContainer}>
      <RenderInput formFormat={formFormat} form={form} column={column} />
    </div>
  )
}

export default RenderForm
