import { FormControl, InputLabel } from '@mui/material'
import Checkbox from '@mui/material/Checkbox'
import FormHelperText from '@mui/material/FormHelperText'
import ListItemText from '@mui/material/ListItemText'
import MenuItem from '@mui/material/MenuItem'
import OutlinedInput from '@mui/material/OutlinedInput'
import Select, { SelectChangeEvent } from '@mui/material/Select'
import { FieldInputProps, FormikProps } from 'formik'
import _get from 'lodash/get'
import _identity from 'lodash/identity'
import _map from 'lodash/map'
import React from 'react'

interface ISelectOption {
  id: string | number;
  label: string | number;
  value: string | number;
}

interface ISelectField {
  field: FieldInputProps<any>;
  form: FormikProps<any>;
  options: ISelectOption[];

  // optional
  label?: string;
  isMultiple?: boolean;
  disabled?: boolean;
  onChange?: (e: SelectChangeEvent<string[]>) => void;
}

function SelectField({
  label,
  isMultiple,
  field,
  form: { touched, errors, setFieldValue },
  options = [],
  disabled,
  onChange = _identity,
}: ISelectField) {
  const { name, value = [] } = field
  const selectId = `select-field-${name}`
  const error = _get(errors, name)
  const isTouched = Boolean(_get(touched, field.name))

  const handleChange = (event: SelectChangeEvent<string[]>) => {
    const {
      target: { value },
    } = event

    setFieldValue(name, value)
    onChange(event)
  }

  const getSelectedItemLabel = (selectedValue: any) => {
    const selectedItem = options.find(option => option.value === selectedValue)
    const label = _get(selectedItem, 'label', '')
    return label
  }

  return (
    <>
      <FormControl
        fullWidth={true}
        disabled={disabled}
        error={isTouched && Boolean(error)}
      >
        {label && <InputLabel id={selectId}>{label}</InputLabel>}
        <Select
          id={name}
          labelId={selectId}
          multiple={isMultiple}
          value={value || []}
          onChange={handleChange}
          input={<OutlinedInput label={label} />}
          renderValue={selected => {
            if (isMultiple) {
              const selectedLabels = _map(selected, (selectedValue: string) =>
                getSelectedItemLabel(selectedValue)
              )
              return selectedLabels.join(', ')
            }

            const selectedLabel = getSelectedItemLabel(selected)
            return selectedLabel
          }}
          sx={{ textAlign: 'start' }}
        >
          {options?.map((option: ISelectOption) => (
            <MenuItem key={option.label} value={option.value}>
              {isMultiple && <Checkbox checked={value.indexOf(option.value) > -1} />}
              <ListItemText primary={option.label} />
            </MenuItem>
          ))}
        </Select>
        {isTouched && Boolean(error) ? (
          <FormHelperText error>{error}</FormHelperText>
        ) : null}
      </FormControl>
    </>
  )
}

export { SelectField }
