import * as React from 'react';
import { translate as _t } from '@assets/js-shop/ShopUtils';
import { useTheme } from '@assets/filters/common/contexts/theme';
import type { ComponentPropsWithoutRef, Ref } from 'react';

type SearchInputProps = React.ComponentPropsWithoutRef<'input'>;

const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
   (props, ref) => {
      return <div className="filter-search-input">
         <i className="c-icon" dangerouslySetInnerHTML={{ __html: require('@assets/icons/search.svg?raw') }} />
         <input type="text" className="form-control" placeholder={_t('searchPlaceholderText')} {...props} ref={ref} />
      </div>;
   },
);

export type FilterSelectEvent = React.ChangeEvent<HTMLInputElement>;

export type MultiChoiceFilterProps = {
   children?: React.ReactNode;
   values: {
      id: number;
      name: React.ReactNode;
      count?: number;
      description?: string;
   }[];

   selected: number[];
   setSelected: (selected: number[], ev: FilterSelectEvent) => void;

   withSearch?: boolean;
   searchRef?: Ref<HTMLInputElement>;
   listProps?: ComponentPropsWithoutRef<'ul'>;
   showProductCounts?: boolean;
};

export function useIdsChangeHandler(
   selected: MultiChoiceFilterProps['selected'],
   setSelected: MultiChoiceFilterProps['setSelected'],
) {
   return React.useCallback((ev: FilterSelectEvent) => {
      if (!ev.currentTarget.value) {
         return;
      }

      const changedId = +ev.currentTarget.value;

      if (ev.currentTarget.checked) {
         setSelected(
            [...selected, changedId],
            ev,
         );

         return;
      }

      setSelected(
         selected.filter(id => id !== changedId),
         ev,
      );
   }, [selected, setSelected]);
}

function kebabizeName(name: string): string {
   return name.replace(/ /g, '-').toLowerCase();
}

export default function MultiChoiceFilter(props: MultiChoiceFilterProps) {
   const {
      values,
      selected,
      setSelected,
      children,
      searchRef,
      listProps,
      showProductCounts = true,
   } = props;
   const { multiChoice: theme } = useTheme();
   const withSearch = props.withSearch ?? theme.withSearch;

   const [search, setSearch] = React.useState('');
   const handleChange = useIdsChangeHandler(selected, setSelected);

   const filteredValues = React.useMemo(() => {
      if (!search || !withSearch) {
         return values;
      }

      return values.filter(({ name }) => String(name).toLowerCase().includes(search.toLowerCase()));
   }, [search, values, withSearch]);

   return (
      <div className="filter-item-values">
         {(withSearch/* && values.length > 4*/) && (
            <SearchInput
               ref={searchRef}
               value={search}
               onChange={ev => setSearch(ev.currentTarget.value)}
            />
         )}
         <ul {...listProps} className={`list-unstyled ${listProps?.className ?? ''}`}>
            {filteredValues.map(({ id, name, count }) => (
               <li key={`mc-${name}-${id}`}>
                  <label className={'custom-control custom-checkbox' + ((count === 0 && !selected.includes(id)) ? ' disabled' : '')} htmlFor={`mc-${kebabizeName(name.toString())}-${id}`}>
                     <input
                        className="custom-control-input"
                        id={`mc-${kebabizeName(name.toString())}-${id}`}
                        type="checkbox"
                        value={id}
                        onChange={handleChange}
                        checked={selected.includes(id)}
                        disabled={!selected.includes(id) && count === 0}
                     />
                     <span className="custom-control-indicator"></span>
                     <span className="custom-control-text">
                        {name} {!!showProductCounts && <small>{count}</small>}
                     </span>
                  </label>
               </li>
            ))}
            {children}
         </ul>
      </div>
   );
}
