import { CheckIcon, XMarkIcon } from '@heroicons/react/24/outline';
import { useEffect, useRef, useState } from 'react';

const AsyncMultiSelect = ({
  onChange,
  queryHook,
  selected = [],
  placeHolder,
  endpoint = '',
  widthClass = 'wmx-w-96',
}) => {
  const searchRef = useRef();
  const dropdownRef = useRef();

  const [skip, setSkip] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');
  const [showSearchResult, setShowSearchResult] = useState(false);
  const [selectedItems, setSelectedItems] = useState(selected);

  const { data, isError, isLoading, error } = queryHook(
    { endpoint, query: { search: searchQuery } },
    {
      skip,
    },
  );

  // handle dropdown outside click
  useEffect(() => {
    const handler = (e) => {
      if (!dropdownRef.current.contains(e.target)) {
        setShowSearchResult(false);
        searchRef.current.value = '';
      }
    };
    document.addEventListener('mousedown', handler);
    return () => {
      document.removeEventListener('mousedown', handler);
    };
  }, []);

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

  // handle item select
  const handleSelect = (item) => {
    if (selectedItems.find((_item) => _item.id === item.id)) {
      setSelectedItems(selectedItems.filter((_item) => _item.id !== item.id));
    } else {
      setSelectedItems((prevState) => [...prevState, item]);
    }
  };

  const handleRemoveItem = (id) => {
    setSelectedItems(selectedItems.filter((_item) => _item.id !== id));
  };

  // debounce functionality start
  const debounceHandler = (fn, delay) => {
    let timeoutId;
    return (...args) => {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        fn(...args);
      }, delay);
    };
  };

  const doSearch = (e) => {
    const query = e.target.value;
    setSearchQuery(query);
    if (query.trim().length === 0) {
      setShowSearchResult(false);
      setSkip(true);
      return;
    }
    setSkip(false);
    setShowSearchResult(true);
  };
  const handleSearch = debounceHandler(doSearch, 500);
  // debounce functionality end

  // set content for different state
  let content = '';

  // item loading state content
  if (isLoading) {
    content = <div className='wmx-py-2 wmx-text-sm'>Searching...</div>;
  }

  // error state content
  if (isError) {
    content = <div className='wmx-py-2 wmx-text-sm wmx-text-red-500'>{error?.data?.message}</div>;
  }

  // successfully item fetching state
  if (showSearchResult && !isError && !isLoading) {
    content = data.map((item) => (
      <div key={item.id} className='wmx-flex wmx-items-center wmx-gap-2 wmx-my-2'>
        <input
          checked={selected.find((_item) => _item.id === item.id)}
          type='checkbox'
          name=''
          id={item.id}
          onChange={() => handleSelect(item)}
          className='!wmx-hidden'
        />

        <label className={`wmx-text-sm wmx-flex wmx-items-center wmx-gap-3 `} htmlFor={item.id}>
          <div
            className={`wmx-shrink-0 wmx-h-4 wmx-w-4 wmx-rounded wmx-border wmx-flex wmx-justify-center wmx-items-center ${
              selected.find((_item) => _item.id === item.id) ? 'wmx-border-primary-dark' : 'wmx-border-gray-500 '
            }`}
          >
            {selected.find((_item) => _item.id === item.id) && <CheckIcon className='wmx-text-primary-dark' />}
          </div>
          {item.image && (
            <img
              className='wmx-shrink-0 wmx-rounded wmx-h-8 wmx-w-8 wmx-object-cover'
              src={item.image}
              alt={item.name}
            />
          )}
          <span className='wmx-text-sm wmx-select-none'>{`${item.id} - ${item.name}`}</span>
        </label>
      </div>
    ));
  }

  return (
    <div ref={dropdownRef} className={`wmx-relative ${widthClass}`}>
      <div className='wmx-relative wmx-border wmx-border-gray-300 wmx-rounded-md'>
        <div
          onClick={() => {
            searchRef.current.focus();
          }}
          className='wmx-flex wmx-gap-1.5 wmx-flex-wrap wmx-items-center !wmx-rounded-md wmx-p-1 wmx-text-sm wmx-outline-none'
        >
          {selected.length > 0 &&
            selected.map((item) => (
              <div
                className='wmx-text-xs wmx-px-1 wmx-py-[3px] wmx-rounded-sm wmx-flex wmx-items-center wmx-bg-gray-300'
                key={item.id}
              >
                <span>{`${item.id} - ${item.name}`}</span>

                <XMarkIcon
                  role='button'
                  onClick={() => handleRemoveItem(item.id)}
                  className='wmx-ml-1 wmx-h-3 wmx-w-3 '
                />
              </div>
            ))}
          <input
            onFocus={(e) => {
              if (e.target.value.length > 0) {
                setShowSearchResult(true);
              }
            }}
            ref={searchRef}
            onChange={handleSearch}
            className='!wmx-border-none !wmx-py-0 !wmx-px-1 !wmx-min-h-[0px] wmx-text-xs '
            type='text'
            placeholder={placeHolder}
          />
        </div>
      </div>
      {showSearchResult && (
        <div className={`wmx-absolute wmx-rounded-md wmx-mt-2 ${widthClass} wmx-shadow-lg wmx-z-50`}>
          <div className='wmx-border wmx-border-gray-300 wmx-custom-scrollbar wmx-rounded-md wmx-bg-white wmx-px-3 wmx-max-h-96 wmx-overflow-y-auto'>
            {content}
          </div>
        </div>
      )}
    </div>
  );
};
export default AsyncMultiSelect;
