import { useFormikContext } from 'formik';
import React, { useMemo } from 'react';
import { Data } from '../../../types';
import { FieldSelection } from '../../FieldSelection';
import {
  CheckboxField,
  CustomTagsField,
  SingleLineTextField,
} from '../../FormElements';
import { BulkEditFieldConfigMap } from './BulkEdit.model';
import { FieldWrapper } from './helpers/FieldWrapper';

export const defaultComponentMap = {
  String: SingleLineTextField,
  BigFloat: SingleLineTextField,
  Boolean: CheckboxField,
  Tags: CustomTagsField, // Map array types to CustomTagsComponent
};

export const BulkEditFormFieldsConfigConverter = (
  config: BulkEditFieldConfigMap,
  componentMap: Record<string, React.ElementType> = defaultComponentMap,
): JSX.Element => {
  const keys = Object.keys(config);

  const FormFields: React.FC = () => {
    const { setFieldValue, setFieldTouched } = useFormikContext<Data>();

    const onFieldRemoved = async (field: string): Promise<void> => {
      // TODO: Update Formik to get the latest types for setFieldValue
      await setFieldValue(field, undefined, false); // setFieldTouched will validate the form
      await setFieldTouched(field, false);
    };

    const onFieldAdded = async (field: string): Promise<void> => {
      await setFieldTouched(field, true); // Mark the field as touched when added
    };

    const fields = useMemo(
      () =>
        keys
          .map((key) => {
            const fieldConfig = config[key];

            // Determine the type of the field
            const fieldType = Array.isArray(fieldConfig.type)
              ? 'Tags' // Treat single String type as Tags
              : fieldConfig.type;

            const Component =
              componentMap[fieldType as keyof typeof componentMap];

            if (!Component) {
              // eslint-disable-next-line no-console
              console.warn(
                `Bulk Edit: No component found for field type: ${fieldType}`,
              );
              return null; // Filter out null entries later
            }

            return (
              <FieldWrapper
                name={key}
                key={key}
                label={fieldConfig.label}
                config={fieldConfig}
                component={Component}
              />
            );
          })
          .filter((element): element is JSX.Element => element !== null),
      [],
    );

    return (
      <FieldSelection
        onFieldRemoved={onFieldRemoved}
        onFieldAdded={onFieldAdded}
        name="bulkedit-fields"
      >
        {fields}
      </FieldSelection>
    );
  };

  return <FormFields />;
};
