import { Field, FormikValues } from 'formik'
import _identity from 'lodash/identity'
import _map from 'lodash/map'
import React, { FC } from 'react'

import { replaceVarInString } from '../../../utils'
import {
  CheckboxField,
  CustomField,
  DatePickerField,
  PhoneNumberField,
  SelectField,
} from '../index'
import { getFieldClassNames, getValidateFunctions, insertHTML } from './utils'

export interface IFieldsSectionProps {
  formFields?: IFormFieldsSection[];
  values: FormikValues;
  setFieldValue: (
    field: string,
    value: FormikValues | string | number,
    shouldValidate?: boolean | undefined
  ) => void;
  disableField?: string;
  countries?: { [key: string]: string | number }[];
  states?: { [key: string]: string | number }[];
  theme?: 'dark' | 'light';
  containerClass?: string;
  setPhoneValidationIsLoading?: (isLoading: boolean) => void;
  onFieldChange?: (name: string, value: string | number) => void;
}

const SectionContainer: FC<{ className: string }> = ({
  children,
  className,
}) => <div className={className}>{children}</div>

export const FieldsSection = ({
  formFields = [],
  countries = [],
  states = [],
  values,
  setFieldValue,
  theme,
  containerClass = '',
  setPhoneValidationIsLoading = _identity,
  onFieldChange = _identity,
  disableField,
}: IFieldsSectionProps) => (
  <>
    {_map(formFields, (item, index) => {
      const {
        name,
        groupLabel,
        groupLabelVars = [],
        groupLabelClassName,
        groupClassName = '',
        fields,
      } = item
      return (
        <SectionContainer key={name} className={groupClassName}>
          <span id={`group_label_${index}`} className={groupLabelClassName}>
            {typeof groupLabel === 'string'
              ? insertHTML(
                  `group_label_${index}`,
                  replaceVarInString(groupLabel, groupLabelVars)
                )
              : groupLabel}
          </span>
          <div className={`fields-container ${groupClassName}`}>
            {_map(fields, (fieldData, fieldIndex) => {
              const {
                name,
                label,
                className = 'full-width',
                type,
                component,
                options = [],
                required,
              } = fieldData
              const id = `${name}-${fieldIndex}`
              const classNames = `${containerClass}-container__field ${className}`
              return (
                component || (
                  <div
                    key={name}
                    id={id}
                    className={getFieldClassNames(id, classNames)}
                  >
                    <Field
                      disabled={name === disableField || name === 'state' && !states.length}
                      name={name}
                      label={`${label}${required ? '' : ' (optional)'}`}
                      type={type}
                      validate={name === 'state' && !states.length ? false : getValidateFunctions({
                        element: fieldData,
                        values,
                      })}
                      setFieldValue={setFieldValue}
                      component={
                        type === 'checkbox'
                          ? CheckboxField
                          : type === 'select'
                          ? SelectField
                          : type === 'phone'
                          ? PhoneNumberField
                          : type === 'date'
                          ? DatePickerField
                          : CustomField
                      }
                      options={
                        name === 'country'
                          ? countries
                          : name === 'state'
                          ? states
                          : options
                      }
                      theme={theme}
                      setPhoneValidationIsLoading={
                        type === 'phone'
                          ? setPhoneValidationIsLoading
                          : undefined
                      }
                      onChange={(e: React.FormEvent<EventTarget>) => {
                        const element = e.target as HTMLInputElement
                        const { value } = element
                        setFieldValue(name, value)
                        onFieldChange(name, value)
                      }}
                      disableDropdown={fieldData.disableDropdown}
                    />
                  </div>
                )
              )
            })}
          </div>
        </SectionContainer>
      )
    })}
  </>
)
