/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import {useState, useRef, useEffect, ChangeEvent} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faCaretDown} from '@fortawesome/free-solid-svg-icons';

import {Tag} from 'components/tags';
import {Label} from 'components/label';
import Checkbox from 'components/forms/Checkbox';
import {Input} from 'components/forms/Input';

import {ISelectItem} from 'interfaces';

import {SelectContainer, Select, DropDownIcon, SelectDropDown, SelectDropDownItem, SelectItemsContainer, SelectedTagsContainer, SubLabel} from './style';

interface IMultiSelectComponent {
  label?: string;
  labelColor?: string;
  items: ISelectItem[];
  searchable?: boolean;
  onSelect: (item: ISelectItem[]) => void;
  defaultItems?: ISelectItem[];
  subLabel?: string;
}

const filterItems = (items: ISelectItem[], searchInput) => {
  return items.filter(({label}) => {
    return label.toLowerCase().indexOf(searchInput.toLowerCase()) > -1;
  });
};

const MultiSelect = ({label, items, onSelect, searchable = false, defaultItems, subLabel, labelColor}: IMultiSelectComponent): React.JSX.Element => {
  const [selectedItems, setSelectedItems] = useState(defaultItems || []);
  const [focusOnSelectComponent, setFocusOnSelectComponent] = useState(false);
  const [filteredItems, setFilteredItems] = useState(items);
  const [showDropDown, setShowDropDown] = useState(false);
  const [searchInput, setSearchInput] = useState('');
  const selectRef = useRef(null);
  const ref = useRef(null);
  const optsRef = useRef([]);
  const handleClickOutside = event => {
    if (ref.current && !ref.current.contains(event.target)) {
      if (selectRef.current && !selectRef.current.contains(event.target)) {
        setShowDropDown(false);
      }
    }
  };

  useEffect(() => {
    document.addEventListener('click', handleClickOutside, true);

    return () => {
      document.removeEventListener('click', handleClickOutside, true);
    };
  });

  useEffect(() => {
    onSelect(selectedItems);
  }, [selectedItems, onSelect]);

  useEffect(() => {
    setFilteredItems(() => filterItems(items, searchInput));
  }, [searchInput, items]);

  const isChecked = item => {
    return selectedItems.map(({value}) => value).indexOf(item) > -1;
  };

  useEffect(() => {
    if (optsRef.current[0]) {
      optsRef.current[0].focus();
    }
  }, [focusOnSelectComponent]);

  const handleFocus = () => {
    setShowDropDown(true);
    setFocusOnSelectComponent(true);
  };

  const handleOnCheck = (event, item) => {
    if (event) {
      event.stopPropagation();
    }

    if (selectedItems.map(({value}) => value).indexOf(item.value) > -1) {
      setSelectedItems(selectedItems.filter(selectedItem => selectedItem.value !== item.value));
    } else {
      setSelectedItems([...selectedItems, item]);
    }
  };

  const generateOptions = () => {
    return filteredItems.map(({label, value}, index) => (
      <SelectDropDownItem key={label}>
        <Checkbox
          value={value}
          onChange={(event: ChangeEvent<unknown>) =>
            handleOnCheck(event, {
              label,
              value
            })
          }
          checked={isChecked(value)}
        />
        <div
          className="drop-down-text"
          role="button"
          ref={ref => (optsRef.current[index] = ref)}
          tabIndex={0}
          onKeyPress={() => null}
          onClick={e =>
            handleOnCheck(e, {
              label,
              value
            })
          }>
          {label}
        </div>
      </SelectDropDownItem>
    ));
  };

  const generateTags = () => {
    return selectedItems.map(({label, value}) => (
      <Tag
        key={value}
        label={label}
        onClose={event =>
          handleOnCheck(event, {
            label,
            value
          })
        }
      />
    ));
  };

  const onInputChange = ({target}) => {
    setSearchInput(target.value);
  };

  const handleOnClickSelect = () => {
    if (focusOnSelectComponent) {
      setFocusOnSelectComponent(!focusOnSelectComponent);

      return;
    }

    setShowDropDown(!showDropDown);
  };

  return (
    <SelectContainer onFocus={handleFocus} tabIndex={0}>
      {!!label && <Label text={label} color={labelColor} />}
      <Select ref={selectRef} showMenu={showDropDown} onClick={handleOnClickSelect} className="testId-selectElement">
        <SelectedTagsContainer>{generateTags()}</SelectedTagsContainer>
        <DropDownIcon>
          <FontAwesomeIcon icon={faCaretDown} />
        </DropDownIcon>
        {showDropDown && (
          <SelectDropDown ref={ref}>
            {searchable && <Input placeholder={'Search...'} value={searchInput} tabIndex={0} onChange={onInputChange} />}
            <SelectItemsContainer searchable={searchable} className="testId-selectOptions">
              {generateOptions()}
            </SelectItemsContainer>
          </SelectDropDown>
        )}
      </Select>
      {subLabel && <SubLabel>{subLabel}</SubLabel>}
    </SelectContainer>
  );
};

export default MultiSelect;
