import React, { Component, FC } from 'react';
import ReactSelect from 'react-select';
import { Props as ReactSelectProps } from 'react-select/lib/Select'; // eslint-disable-line import/no-unresolved
import { withTheme, ThemeInterface } from '../../styles';
import { inputs } from '../../styles/utils';
import { Option, OptionType } from './Option';
import { DropdownIndicator } from './DropdownIndicator';

export type variants = 'primary' | 'ghost';

export interface SelectProps<OptT extends { value: any } = any>
  extends ReactSelectProps<OptT> {
  theme?: any;
  onChange?: (value: OptT['value']) => void;
  onBlur?: () => void;
  variant?: variants;
  name?: string;
  disabledOptionText?: string;
  placeholder?: any;
  noIcon?: boolean;
}

const getStyles = (theme: ThemeInterface, variant: variants) => {
  const inputsStyles = inputs({ theme });

  return {
    primary: {
      container: (styles: any) => ({
        ...styles,
        minHeight: inputsStyles.height,
        minWidth: '7rem',
      }),
      control: (styles: any, state: any) => {
        return {
          ...styles,
          borderRadius: theme.radii[1],
          boxShadow: 'none',
          borderColor: theme.colors.placeholder,
          ...(state.isFocused &&
            ({
              borderColor: theme.colors.brandMain,
              '&:hover': {
                borderColor: theme.colors.brandMain,
              },
            } as any)),
        };
      },
      valueContainer: (styles: any) => ({
        ...styles,
        paddingLeft: '14px',
        fontSize: theme.fontSizes[1],
        minHeight: inputsStyles.height,
      }),
      dropdownIndicator: (styles: any) => ({
        ...styles,
        paddingRight: '16px',
        color: theme.colors.placeholder,
      }),
      menu: (styles: any) => ({
        ...styles,
        minWidth: '20rem',
      }),
      menuPortal: (styles: any) => ({
        ...styles,
        zIndex: 1000,
      }),
    },
    ghost: {
      container: (styles: any) => ({
        ...styles,
        minWidth: '2rem',
      }),
      control: (styles: any) => {
        return {
          ...styles,
          boxShadow: 'none',
          border: 'none',
          backgroundColor: '',
        };
      },
      valueContainer: (styles: any) => ({
        ...styles,
        paddingRight: 0,
        paddingLeft: 0,
        fontSize: theme.fontSizes[1],
      }),
      dropdownIndicator: (styles: any) => ({
        ...styles,
        paddingRight: 0,
        color: theme.colors.placeholder,
        '&:hover': {
          color: theme.colors.brandMain,
        },
      }),
      menu: (styles: any) => ({
        ...styles,
        minWidth: '20rem',
      }),
      menuPortal: (styles: any) => ({
        ...styles,
        zIndex: 1000,
      }),
    },
  }[variant];
};

class SelectPrimitiveBase extends Component<SelectProps> {
  public static defaultProps = {
    isClearable: false,
    isSearchable: false,
    variant: 'primary',
    onBlur: () => {},
    placeholder: 'Select...',
  };

  public handleChange = (value?: OptionType | OptionType[] | null) => {
    const { onChange, onBlur } = this.props;

    if (onChange) {
      if (!value) {
        onChange(value);
      } else {
        const result = Array.isArray(value)
          ? value.map((option) => option.value)
          : value.value;
        onChange(result);
      }
    }

    if (onBlur) {
      onBlur();
    }
  };

  public render() {
    const {
      theme,
      variant,
      name,
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      onChange,
      value,
      options,
      components,
      styles,
      inputRef,
      placeholder,
      noIcon,
      ...otherProps
    } = this.props;

    return (
      <ReactSelect
        inputId={name}
        ref={inputRef}
        inputRef={inputRef}
        innerRef={inputRef}
        name={name}
        styles={
          theme && variant
            ? {
                ...getStyles(theme, variant),
                ...styles,
              }
            : {}
        }
        components={{
          IndicatorSeparator: null,
          ClearIndicator: null,
          DropdownIndicator,
          Option: (optionProps) => Option({ ...optionProps, noIcon }),
          ...components,
        }}
        backspaceRemovesValue={false}
        onChange={this.handleChange}
        menuPlacement="auto"
        menuPortalTarget={document.body}
        options={options}
        placeholder={placeholder}
        value={
          value === null || (value && Array.isArray(value))
            ? value
            : options?.find((option: OptionType) => option.value === value)
        }
        {...otherProps}
      />
    );
  }
}

const ThemedSelectPrimitive = withTheme(SelectPrimitiveBase);

export const Select: FC<SelectProps> = Object.assign(ThemedSelectPrimitive, {
  defaultProps: SelectPrimitiveBase.defaultProps,
  name: 'Select',
});
