import React, { useRef, useState, useEffect, useMemo } from 'react';
import Select from '@/_ui/Select';
import { components } from 'react-select';
import defaultStyles from '@/_ui/Select/styles';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { Checkbox } from '@/_ui/CheckBox/CheckBox';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import { isArray, isString } from 'lodash';
const { MenuList } = components;

const SCALING_FACTOR = 0.6;
const FONT_SIZE = 12;
const PADDING = 12;
const MARGIN = 10; // including left and right side

export const CustomSelect = ({
  options,
  value,
  onChange,
  fuzzySearch = false,
  placeholder,
  disabled,
  className,
  darkMode,
  defaultOptionsList,
  textColor = '',
  isMulti,
  containerWidth,
  optionsLoadingState = false,
  horizontalAlignment = 'left',
  isEditable,
  isMaxRowHeightAuto,
}) => {
  const containerRef = useRef(null);
  const inputRef = useRef(null); // Ref for the input search box
  const [isFocused, setIsFocused] = useState(false);
  useEffect(() => {
    const handleDocumentClick = (event) => {
      if (isMulti && !containerRef.current?.contains(event.target)) {
        setIsFocused(false);
      }
    };

    document.addEventListener('mousedown', handleDocumentClick);

    return () => {
      document.removeEventListener('mousedown', handleDocumentClick);
    };
  }, []);

  useEffect(() => {
    // Focus the input search box when the menu list is open and the component is focused
    if (isFocused && inputRef.current) {
      inputRef.current.focus();
    }
  }, [isFocused]);

  const customStyles = {
    ...defaultStyles(darkMode, '100%'),
    ...(isMulti && {
      multiValue: (provided) => ({
        ...provided,
        display: 'inline-block', // Display selected options inline
        marginRight: '4px', // Add some space between options
      }),
    }),
    valueContainer: (provided) => ({
      ...provided,
      ...(isMulti && {
        marginBottom: '0',
        display: 'flex',
        flexWrap: 'no-wrap',
        overflow: 'hidden',
        flexDirection: 'row',
      }),
      justifyContent: horizontalAlignment,
    }),
    menuList: (base) => ({
      ...base,
      backgroundColor: 'var(--surfaces-surface-01) ',
      color: 'var(--text-primary)',
      cursor: 'pointer',
      overflow: 'auto',
    }),
    multiValueLabel: (provided) => ({
      ...provided,
      padding: '2px 6px',
      background: 'var(--surfaces-surface-03)',
      margin: '0 5px',
      borderRadius: '6px',
      color: textColor || 'var(--text-primary)',
      fontSize: '12px',
    }),
    singleValue: (provided) => ({
      ...provided,
      padding: '2px 6px',
      background: 'var(--surfaces-surface-03)',
      margin: '0 5px',
      borderRadius: '6px',
      color: textColor || 'var(--text-primary)',
      fontSize: '12px',
    }),
  };
  const customComponents = {
    MenuList: (props) => <CustomMenuList {...props} optionsLoadingState={optionsLoadingState} inputRef={inputRef} />,
    Option: CustomMultiSelectOption,
    DropdownIndicator: isEditable ? DropdownIndicator : null,
    ...(isMulti && {
      MultiValueRemove,
      MultiValueContainer: CustomMultiValueContainer,
    }),
  };
  const defaultValue = useMemo(() => {
    if (defaultOptionsList.length >= 1) {
      return !isMulti ? defaultOptionsList[defaultOptionsList.length - 1] : defaultOptionsList;
    }
  }, [isMulti, defaultOptionsList]);

  const _value = useMemo(() => {
    // Return null to show default value
    if (!value) {
      return null;
    }
    if (isMulti && value?.length) {
      if (isArray(value)) {
        return options?.filter((option) =>
          value?.find((val) => {
            if (val.hasOwnProperty('value')) {
              return option.value === val.value;
            } else return option.value === val;
          })
        );
      } else {
        return []; // Return empty array to not show default value in case of wrong value to be set
      }
    } else {
      // Condition for single select
      return options?.find((option) => option.value === value) || [];
    }
  }, [options, value, isMulti]);

  const calculateIfPopoverRequired = (value, containerWidth) => {
    let totalWidth = 0;

    // // Calculate total width of all span elements
    for (const option of value) {
      const valueWidth = option.label.length * FONT_SIZE * SCALING_FACTOR + PADDING + MARGIN;
      // Check if max row height is auto and then if any of the options width exceeds container width, return true
      if (isMaxRowHeightAuto) {
        if (valueWidth > containerWidth) {
          return true;
        }
      } else {
        totalWidth += valueWidth + 4; // Adding 4px to be safe
      }
    }
    return totalWidth > containerWidth; // Return based on total width comparison
  };

  return (
    <OverlayTrigger
      placement="bottom"
      overlay={
        isMulti && (_value?.length || defaultValue?.length) && !isFocused ? (
          getOverlay(_value ? _value : defaultValue, containerWidth, darkMode)
        ) : (
          <div></div>
        )
      }
      trigger={
        isMulti &&
        !isFocused &&
        calculateIfPopoverRequired(_value ? _value : defaultValue, containerWidth - 40) && ['hover', 'focus']
      } //container width -24 -16 gives that select container size
      rootClose={true}
    >
      <div className="w-100 h-100 d-flex align-items-center">
        <Select
          options={options}
          hasSearch={false}
          fuzzySearch={fuzzySearch}
          isDisabled={disabled}
          className={className}
          components={customComponents}
          value={_value}
          onMenuInputFocus={() => setIsFocused(true)}
          onChange={(value) => {
            setIsFocused(false);
            onChange(value);
          }}
          useCustomStyles={true}
          styles={customStyles}
          defaultValue={defaultValue}
          placeholder={placeholder}
          isMulti={isMulti}
          hideSelectedOptions={false}
          isClearable={false}
          clearIndicator={false}
          {...{
            menuIsOpen: isFocused || undefined,
            isFocused: isFocused || undefined,
          }}
        />
      </div>
    </OverlayTrigger>
  );
};

const CustomMenuList = ({ optionsLoadingState, children, selectProps, inputRef, ...props }) => {
  const { onInputChange, inputValue, onMenuInputFocus } = selectProps;

  return (
    <div className="table-select-custom-menu-list" onClick={(e) => e.stopPropagation()}>
      <div className="table-select-column-type-search-box-wrapper ">
        {!inputValue && (
          <span className="">
            <SolidIcon name="search" width="14" />
          </span>
        )}
        <input
          autoCorrect="off"
          autoComplete="off"
          spellCheck="false"
          type="text"
          value={inputValue}
          onChange={(e) =>
            onInputChange(e.currentTarget.value, {
              action: 'input-change',
            })
          }
          onMouseDown={(e) => {
            e.stopPropagation();
            e.target.focus();
          }}
          onTouchEnd={(e) => {
            e.stopPropagation();
            e.target.focus();
          }}
          onFocus={onMenuInputFocus}
          placeholder="Search..."
          className="table-select-column-type-search-box"
          ref={inputRef} // Assign the ref to the input search box
        />
      </div>
      <MenuList {...props} selectProps={selectProps}>
        {optionsLoadingState ? (
          <div class="text-center py-4">
            <div class="spinner-border text-primary" role="status">
              <span class="sr-only"></span>
            </div>
          </div>
        ) : (
          children
        )}
      </MenuList>
    </div>
  );
};

const CustomMultiSelectOption = ({ innerRef, innerProps, children, isSelected, ...props }) => {
  return (
    <div ref={innerRef} {...innerProps} className="option-wrapper d-flex">
      {props.isMulti ? (
        <Checkbox label="" isChecked={isSelected} onChange={(e) => e.stopPropagation()} key="" value={children} />
      ) : (
        <div style={{ visibility: isSelected ? 'visible' : 'hidden' }}>
          <Checkbox label="" isChecked={isSelected} onChange={(e) => e.stopPropagation()} key="" value={children} />
        </div>
      )}
      {children}
    </div>
  );
};

const MultiValueRemove = (props) => {
  const { innerProps } = props;
  return <div {...innerProps} />;
};
const CustomMultiValueContainer = (props) => {
  return (
    <div
      style={{
        display: 'flex',
        flexWrap: 'wrap',
        alignItems: 'center',
        gap: '4px',
      }}
    >
      {props.children}
    </div>
  );
};

const getOverlay = (value, containerWidth, darkMode) => {
  const getLabel = (option) => {
    if (option?.hasOwnProperty('label')) {
      return option.label;
    } else if (isString(option)) {
      return option;
    } else return '';
  };

  return Array.isArray(value) ? (
    <div
      style={{
        maxWidth: '266px',
      }}
      className={`overlay-cell-table overlay-multiselect-table ${darkMode && 'dark-theme'}`}
    >
      {value?.map((option) => {
        return (
          <span
            style={{
              padding: '2px 6px',
              background: 'var(--surfaces-surface-03)',
              borderRadius: '6px',
              color: 'var(--text-primary)',
              fontSize: '12px',
            }}
            key={getLabel(option)}
          >
            {getLabel(option)}
          </span>
        );
      })}
    </div>
  ) : (
    <div></div>
  );
};

const DropdownIndicator = (props) => {
  return (
    <div {...props} className="cell-icon-display">
      {/* Your custom SVG */}
      {props.selectProps.menuIsOpen ? (
        <SolidIcon name="arrowUpTriangle" width="16" height="16" fill={'#6A727C'} />
      ) : (
        <SolidIcon name="arrowDownTriangle" width="16" height="16" fill={'#6A727C'} />
      )}
    </div>
  );
};
