import React, { useEffect, useState } from 'react';
import type { AutocompleteChangeReason } from '@mui/material';

import { SIZE_MEDIUM, SIZE_SMALL } from '@/mui/constants';

import { TagType } from '../types';

import StateSelect from '../components/StateSelect/StateSelect';
import TagList from '../components/TagList/TagList';
import { Autocomplete, Stack, TextField } from '@/mui/components';

type Props = {
  size?: typeof SIZE_SMALL | typeof SIZE_MEDIUM;
  value: TagType[];
  options?: Array<{
    label: string;
    value: string | number;
  }>;
  placeholder?: string;
  include: boolean;
  disabled: boolean;
  selectProps: { [key: string]: unknown };
  onChange: (
    event: React.SyntheticEvent,
    option: unknown | unknown[] | object[],
    reason: AutocompleteChangeReason,
  ) => void;
  onInputChange?: (event: React.SyntheticEvent, query: string) => void;
  onOpen?: () => void;
  onClose?: () => void;
  getTagLabel?: () => void;
};

function TagSelector({
  size = 'medium',
  value = [],
  options = [],
  placeholder,
  onChange,
  onInputChange,
  onOpen,
  onClose,
  include,
  disabled,
  getTagLabel,
  selectProps = {},
  ...restProps
}: Props) {
  const [stateInclude, toggleInclude] = useState(include ?? true);
  const [searchText, setSearchText] = useState('');
  const [selectedTags, setSelectedTags] = useState(value);
  const [stateOptions, setOptions] = useState(options);

  useEffect(() => {
    toggleInclude(include ?? true);
  }, [include]);

  useEffect(() => {
    setSelectedTags(value);
  }, [value]);

  useEffect(() => {
    setOptions(options);
  }, [options]);

  return (
    <Stack spacing={1} fullWidth>
      <Stack fullWidth spacing={2} direction="row" alignItems="flex-start">
        <div>
          <StateSelect
            disabled={!!disabled}
            {...selectProps}
            size={size}
            value={stateInclude}
            onChange={(state) => toggleInclude(state)}
          />
        </div>
        <Autocomplete
          onOpen={onOpen}
          onClose={onClose}
          disabled={disabled}
          {...restProps}
          multiple
          renderTags={() => null}
          size={size}
          inputValue={searchText}
          value={selectedTags}
          options={stateOptions.filter(({ value: value$ }) => !selectedTags.some((tag) => tag.value === value$))}
          optionLabelKey="label"
          optionValueKey="value"
          disableClearable={false}
          onChange={(event, tags, reason) => {
            const tags$ = tags as TagType[];
            const resultTags = tags$.map((tag) => ({
              ...tag,
              include: tag.include ?? stateInclude,
            }));

            setSelectedTags(resultTags);
            onChange(event, resultTags, reason);

            setSearchText('');
          }}
          onInputChange={(event, query) => {
            setSearchText(query);

            if (onInputChange) {
              onInputChange(event, query);
            }
          }}
          renderInput={(params) => (
            <TextField
              {...params}
              size={size}
              placeholder={placeholder}
              onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
                if (!searchText && event.key === 'Backspace') {
                  event.stopPropagation();
                }
              }}
            />
          )}
        />
      </Stack>
      <TagList
        disabled={!!disabled}
        size={size}
        tags={selectedTags}
        getTagLabel={getTagLabel}
        onDelete={(event, tag) => {
          const tags = selectedTags.filter((tag$) => tag$.value !== tag.value);

          setSelectedTags(tags);

          onChange(event, tags, 'removeOption');
        }}
      />
    </Stack>
  );
}

export default TagSelector;
