import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'clsx';

import { CUSTOM_LABEL_VALUE_SIZE } from '../../../../../../constants';
import { CustomTagsPropType, SystemTagsPropType } from '../../../../../../constants/propTypes';

import { selectedCategorySelector, selectedTagSelector, tagsOptionsSelector } from '../../../../../../redux/selectors';
import { getCustomTagsWithCategoryOptionsAction, setStateAction } from '../../../../../../redux/slices';
import { autoSuggestHighlight } from '@/mui/helpers';

import { Autocomplete, Box, Button, InputAdornment, Stack, TextField, Typography } from '@/mui/components';

import styles from './WithoutCategory.module.scss';

function WithoutCategory(props) {
  const dispatch = useDispatch();
  const [inputValue, setInputValue] = useState('');
  const [open, setOpen] = useState(false);

  const selectedTag = useSelector(selectedTagSelector);
  const tagsOptions = useSelector(tagsOptionsSelector);
  const selectedCategory = useSelector(selectedCategorySelector);

  // general handlers
  const handleSelectTag = (tag) => {
    if (!tag?.categoryLabelId) {
      return;
    }

    dispatch(
      setStateAction({
        selectedTag: tag,
        selectedCategory: {
          id: tag.categoryLabelId,
          name: tag.categoryName,
          label: tag.categoryName,
          value: tag.categoryName,
          color: tag.categoryColor,
          group: 'CUSTOM',
        },
      }),
    );

    if (tag?.label) {
      setInputValue(tag.label);
    }

    setOpen(false);
  };

  const handleGetTagOptions = (searchText = inputValue) => {
    dispatch(
      getCustomTagsWithCategoryOptionsAction({
        searchText,
        accountId: props.accountId,
      }),
    );

    setInputValue(searchText);
    setOpen(true);
  };

  const handleCreateTag = () => {
    const category = {
      id: selectedTag.categoryLabelId,
      name: selectedTag.categoryName,
      label: selectedTag.categoryName,
      value: selectedTag.categoryName,
      color: selectedTag.categoryColor,
      group: 'CUSTOM',
    };

    props.onCreateCustomTag({
      tagValue: inputValue.trim(),
      category,
    });

    dispatch(
      setStateAction({
        selectedCategory: category,
        selectedTag: null,
        tagsOptions: [],
      }),
    );

    setOpen(false);
  };

  useEffect(() => {
    if (!selectedCategory) {
      setInputValue('');

      dispatch(
        setStateAction({
          selectedTag: null,
          tagsOptions: [],
        }),
      );

      setOpen(false);
    }
  }, [selectedCategory]);

  const getRenderInput = (params) => {
    const isDisabled = () => !selectedTag?.value;

    return (
      <TextField
        {...params}
        size="small"
        variant="outlined"
        placeholder="Tag Name"
        inputProps={{
          ...params.inputProps,
          maxLength: CUSTOM_LABEL_VALUE_SIZE,
        }}
        InputProps={{
          ...params.InputProps,
          classes: {
            root: classNames({
              [styles.Input]: params.inputProps.value,
            }),
          },
          endAdornment: (
            <InputAdornment position="end">
              {params.InputProps.endAdornment}
              <Button
                variant="contained"
                size="small"
                color="primary"
                shape="rounded"
                label="Add"
                disabled={props.disabled || isDisabled()}
                onClick={handleCreateTag}
              >
                Add
              </Button>
            </InputAdornment>
          ),
        }}
      />
    );
  };

  return (
    <Autocomplete
      fullWidth
      size="small"
      freeSolo
      open={open}
      value={selectedTag}
      inputValue={inputValue}
      options={tagsOptions || []}
      optionValueKey="label"
      disabled={props.disabled}
      filterOptions={(options) =>
        options.filter((option) => {
          const isExist = props.customTags.some(
            (currentTag) =>
              currentTag.labelId === option.categoryLabelId &&
              currentTag.name === option.categoryName &&
              currentTag.value === option.value,
          );

          return !isExist;
        })
      }
      renderInput={getRenderInput}
      renderOption={(optionProps, option) => (
        <Box
          {...optionProps}
          key={`${option.categoryLabelId}_${option.label}`}
          component="li"
          className={optionProps.className}
        >
          <Stack direction="row" spacing={2}>
            <Typography variant="caption" color="text.primary">
              {autoSuggestHighlight(inputValue, option.label).map((part) => {
                const Tag = part.highlight ? 'b' : React.Fragment;

                return <Tag key={part.id}>{part.text}</Tag>;
              })}
            </Typography>

            <Typography variant="caption" color="text.primary">
              {`(${option.categoryName})`}
            </Typography>
          </Stack>
        </Box>
      )}
      onOpen={(e) => handleGetTagOptions(e.target?.value)}
      onInputChange={(e, searchText, reason) => handleGetTagOptions(searchText, reason)}
      onChange={(e, value) => handleSelectTag(value)}
      onClose={() => setOpen(false)}
    />
  );
}

WithoutCategory.propTypes = {
  // from props
  accountId: PropTypes.number.isRequired,
  customTags: CustomTagsPropType.isRequired,
  systemTags: SystemTagsPropType.isRequired,
  disabled: PropTypes.bool.isRequired,
  onCreateCustomTag: PropTypes.func.isRequired,
  onCreateSystemTag: PropTypes.func.isRequired,
};

export default WithoutCategory;
