import {
  Autocomplete,
  Checkbox,
  CircularProgress,
  TextField,
} from "@mui/material";
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
import CheckBoxIcon from "@mui/icons-material/CheckBox";

export interface MultiSelectOption<TValue = number | string> {
  readonly value: TValue;
  readonly label: string;
}

interface MultiSelectProps<TValue = number | string> {
  readonly options: MultiSelectOption<TValue>[];
  readonly value: TValue[];
  readonly onChange: (values: TValue[]) => void;
  readonly label?: string;
  readonly placeholder?: string;
  readonly loading?: boolean;
  readonly disabled?: boolean;
  readonly error?: boolean;
  readonly helperText?: string;
  readonly size?: "small" | "medium";
  readonly fullWidth?: boolean;
}

export function MultiSelect<TValue = number | string>({
  options,
  value,
  onChange,
  label,
  placeholder,
  loading = false,
  disabled = false,
  error = false,
  helperText,
  size = "small",
  fullWidth = true,
}: MultiSelectProps<TValue>) {
  const selectedOptions = options.filter((opt) => value.includes(opt.value));

  return (
    <Autocomplete
      multiple
      disableCloseOnSelect
      fullWidth={fullWidth}
      size={size}
      disabled={disabled}
      loading={loading}
      options={options}
      value={selectedOptions}
      getOptionLabel={(option) => option.label}
      isOptionEqualToValue={(option, selected) => option.value === selected.value}
      onChange={(_, newSelected) => {
        onChange(newSelected.map((opt) => opt.value));
      }}
      renderOption={(props, option, { selected }) => {
        const { key, ...rest } = props as React.HTMLAttributes<HTMLLIElement> & { key: React.Key };
        return (
          <li key={key} {...rest}>
            <Checkbox
              icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
              checkedIcon={<CheckBoxIcon fontSize="small" />}
              style={{ marginRight: 8 }}
              checked={selected}
            />
            {option.label}
          </li>
        );
      }}
      renderInput={(params) => (
        <TextField
          {...params}
          label={label}
          placeholder={selectedOptions.length === 0 ? placeholder : undefined}
          error={error}
          helperText={helperText}
          slotProps={{
            input: {
              ...params.InputProps,
              endAdornment: (
                <>
                  {loading && <CircularProgress color="inherit" size={16} />}
                  {params.InputProps.endAdornment}
                </>
              ),
            },
          }}
        />
      )}
    />
  );
}
