/**
 * GenericFormField Component
 */

import React from 'react';
import { Field, useFormikContext } from 'formik';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import dayjs from 'dayjs';
import { mdiUpload } from '@mdi/js';

import FormField from '../FormField';
import FormImagePicker from '../FormImagePicker';
import { SelectField } from '../SelectField';
import { SelectFieldMany } from '../SelectFieldMany';
import { SwitchField } from '../SwitchField';
import type { FormFieldConfig } from '../../types/forms';

interface GenericFormFieldProps {
  config: FormFieldConfig;
  // Current form values for select fields that need initial options
  initialValues?: Record<string, unknown>;
}

const GenericFormField: React.FC<GenericFormFieldProps> = ({
  config,
  initialValues,
}) => {
  const { values, setFieldValue } = useFormikContext<Record<string, unknown>>();

  switch (config.type) {
    case 'text':
    case 'email':
    case 'password':
      return (
        <FormField label={config.label}>
          <Field
            name={config.name}
            type={config.type}
            placeholder={config.placeholder || config.label}
          />
        </FormField>
      );

    case 'number':
      return (
        <FormField label={config.label}>
          <Field
            name={config.name}
            type='number'
            placeholder={config.placeholder || config.label}
            min={config.min}
            max={config.max}
          />
        </FormField>
      );

    case 'textarea':
      return (
        <FormField label={config.label}>
          <Field
            name={config.name}
            as='textarea'
            placeholder={config.placeholder || config.label}
            rows={4}
          />
        </FormField>
      );

    case 'richtext':
      return (
        <FormField label={config.label}>
          <Field
            name={config.name}
            as='textarea'
            placeholder={config.placeholder || config.label}
            rows={6}
          />
        </FormField>
      );

    case 'select':
      return (
        <FormField label={config.label} labelFor={config.name}>
          <Field
            name={config.name}
            id={config.name}
            component={SelectField}
            options={initialValues?.[config.name]}
            itemRef={config.itemRef}
            showField={config.showField || 'name'}
          />
        </FormField>
      );

    case 'multiselect':
      return (
        <FormField label={config.label} labelFor={config.name}>
          <Field
            name={config.name}
            id={config.name}
            component={SelectFieldMany}
            options={initialValues?.[config.name]}
            itemRef={config.itemRef}
            showField={config.showField || 'name'}
          />
        </FormField>
      );

    case 'enum':
      return (
        <FormField label={config.label} labelFor={config.name}>
          <Field name={config.name} id={config.name} component='select'>
            {config.options?.map((option) => (
              <option key={option.value} value={option.value}>
                {option.label}
              </option>
            ))}
          </Field>
        </FormField>
      );

    case 'boolean':
    case 'switch':
      return (
        <FormField label={config.label} labelFor={config.name}>
          <Field name={config.name} id={config.name} component={SwitchField} />
        </FormField>
      );

    case 'date':
      return (
        <FormField label={config.label}>
          <DatePicker
            dateFormat='yyyy-MM-dd'
            selected={
              values[config.name]
                ? new Date(
                    dayjs(values[config.name] as string).format('YYYY-MM-DD'),
                  )
                : null
            }
            onChange={(date: Date | null) => setFieldValue(config.name, date)}
          />
        </FormField>
      );

    case 'datetime':
      return (
        <FormField label={config.label}>
          <DatePicker
            dateFormat='yyyy-MM-dd hh:mm'
            showTimeSelect
            selected={
              values[config.name]
                ? new Date(
                    dayjs(values[config.name] as string).format(
                      'YYYY-MM-DD hh:mm',
                    ),
                  )
                : null
            }
            onChange={(date: Date | null) => setFieldValue(config.name, date)}
          />
        </FormField>
      );

    case 'image':
      return (
        <FormField>
          <Field
            label={config.label}
            color='info'
            icon={mdiUpload}
            path={config.uploadPath || `${config.itemRef}/${config.name}`}
            name={config.name}
            id={config.name}
            schema={
              config.fileSchema || { size: undefined, formats: undefined }
            }
            component={FormImagePicker}
          />
        </FormField>
      );

    case 'file':
      return (
        <FormField>
          <Field
            label={config.label}
            color='info'
            icon={mdiUpload}
            path={config.uploadPath || `${config.itemRef}/${config.name}`}
            name={config.name}
            id={config.name}
            schema={
              config.fileSchema || { size: undefined, formats: undefined }
            }
            component={FormImagePicker}
          />
        </FormField>
      );

    default:
      return (
        <FormField label={config.label}>
          <Field
            name={config.name}
            placeholder={config.placeholder || config.label}
          />
        </FormField>
      );
  }
};

export default GenericFormField;
