import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';

import types from './types';

import * as selectors from '../redux/selectors';
import {
  accountGetOwnersAction,
  accountSearchPrefixAction,
  accountTypeAction,
  feedDescriptionSearchPrefixAction,
  feedDescriptionTypeAction,
  hubsSearchPrefixAction,
  hubsTypeAction,
  keywordListAction,
  keywordSearchPrefixAction,
  keywordTypeAction,
  labelSearchPrefixAction,
  labelTypeAction,
} from '../redux/slices';
import { getLanguageOptions } from '@/modules/@common/helpers/videoLangs';

import ActionAutocomplete from './ActionAutocomplete';
import ActionIAB from './ActionIAB';
import AutocompleteFilter from './Autocomplete';

function FilterSuggesterComponent(props) {
  const dispatch = useDispatch();

  const keywordListLoading = useSelector(selectors.keywordListLoadingSelector);
  const labelListLoading = useSelector(selectors.labelListLoadingSelector);
  const feedDescriptionListLoading = useSelector(selectors.feedDescriptionListLoadingSelector);
  const keywordList = useSelector(selectors.keywordListSelector);
  const labelList = useSelector(selectors.labelListSelector);
  const feedDescriptionList = useSelector(selectors.feedDescriptionListSelector);
  const accountList = useSelector(selectors.accountListSelector);
  const accountListLoading = useSelector(selectors.accountListLoadingSelector);
  const hubsList = useSelector(selectors.hubsListSelector);
  const hubsListLoading = useSelector(selectors.hubsListLoadingSelector);

  const languageOptions = useMemo(() => getLanguageOptions(), []);

  const handleSuggesterOnFocus = (value) => {
    dispatch(keywordListAction());
    dispatch(keywordTypeAction(props.config.type));
    dispatch(keywordSearchPrefixAction(value));
  };

  const keywordSearchPrefixWrapperAction = (value) => {
    dispatch(keywordTypeAction(props.config.type));
    dispatch(keywordSearchPrefixAction(value));

    return value;
  };

  const labelSearchPrefixWrapperAction = (options) => {
    dispatch(labelTypeAction(props.config.type));
    dispatch(labelSearchPrefixAction(options));

    return options.prefix;
  };

  const feedDescriptionSearchPrefixWrapperAction = (options) => {
    dispatch(feedDescriptionTypeAction(props.config.type));
    dispatch(feedDescriptionSearchPrefixAction(options));

    return options.prefix;
  };

  const accountSearchPrefixWrapperAction = (options) => {
    dispatch(accountTypeAction(props.config.type));
    dispatch(accountSearchPrefixAction(options));

    return options.prefix;
  };

  const hubsSearchPrefixWrapperAction = (options) => {
    dispatch(hubsTypeAction(props.config.type));
    dispatch(hubsSearchPrefixAction(options));

    return options.prefix;
  };

  const wrapperAction = (value) => {
    props.selectAction({
      ...props.config,
      value,
    });
  };

  const customPropsCollection = {
    [types.categories]: () => ({
      loading: keywordListLoading,
      options: keywordList,
      onChange: wrapperAction,
    }),
    [types.labels]: () => ({
      onOpen: () =>
        dispatch(
          labelSearchPrefixAction({
            owner: props.contentOwners.map((owner) => +owner),
            prefix: '',
          }),
        ),
      onInputChange: (value) => {
        labelSearchPrefixWrapperAction({
          owner: props.contentOwners.map((owner) => +owner),
          prefix: value,
        });
      },
      loading: labelListLoading,
      options: labelList,
      onChange: wrapperAction,
      isOptionEqualToValue: (option, value) => option.name === value.name && option.value === value.value,
    }),
    [types.hubs]: () => ({
      onOpen: () =>
        dispatch(
          hubsSearchPrefixAction({
            prefix: '',
          }),
        ),
      onInputChange: (value) => {
        hubsSearchPrefixWrapperAction({
          prefix: value,
        });
      },
      loading: hubsListLoading,
      options: hubsList,
      onChange: wrapperAction,
    }),
    [types.source]: () => {
      const feedDescriptionListCopy = [...feedDescriptionList];
      return {
        onOpen: () =>
          dispatch(
            feedDescriptionSearchPrefixAction({
              owner: props.contentOwners.map((owner) => +owner),
              prefix: '',
            }),
          ),
        onInputChange: (value) => {
          feedDescriptionSearchPrefixWrapperAction({
            owner: props.contentOwners.map((owner) => +owner),
            prefix: value,
          });
        },
        loading: feedDescriptionListLoading,
        options: feedDescriptionListCopy.sort((a, b) => a.label.localeCompare(b.label)),
        onChange: wrapperAction,
      };
    },
    [types.languages]: () => ({
      loading: keywordListLoading,
      options: languageOptions,
      onChange: wrapperAction,
    }),
    [types.account]: () => ({
      onOpen: () =>
        dispatch(
          accountSearchPrefixAction({
            prefix: '',
          }),
        ),
      onInputChange: (value) => {
        accountSearchPrefixWrapperAction({
          prefix: value,
        });
      },
      loading: accountListLoading,
      options: accountList,
      onChange: wrapperAction,
      onGetContentOwners: (v) => dispatch(accountGetOwnersAction(v)),
    }),
    defaultFn: () => ({
      onOpen: () => {
        handleSuggesterOnFocus({
          owner: props.contentOwners.map((owner) => +owner),
          prefix: '',
        });
      },
      onInputChange: (value) => {
        keywordSearchPrefixWrapperAction({
          owner: props.contentOwners.map((owner) => +owner),
          prefix: value,
        });
      },
      loading: keywordListLoading,
      options: keywordList,
      onChange: wrapperAction,
    }),
  };

  const components = [
    {
      Component: ActionIAB,
      componentProps: {
        id: `autocomplete-${props.config.label}`,
        placeholder: `Search ${props.config.label}`,
        value: props.selected,
        highlight: true,
      },
      active: props.config.type === types.categories,
    },
    {
      Component: AutocompleteFilter,
      componentProps: {
        id: `autocomplete-${props.config.label}`,
        placeholder: `Search ${props.config.label}`,
        value: props.selected,
        groupBy: (option) => option.groupBy,
        isFilterDirty: props.isFilterDirty,
      },
      active: props.config.type === types.account,
    },
    {
      Component: ActionAutocomplete,
      componentProps: {
        id: `autocomplete-${props.config.label}`,
        placeholder: `Search ${props.config.label}`,
        value: props.selected,
        groupBy: (option) => option.groupBy,
        isFilterDirty: props.isFilterDirty,
      },
      active: props.config.type === types.labels,
    },
    {
      Component: ActionAutocomplete,
      componentProps: {
        id: `autocomplete-${props.config.label}`,
        placeholder: `Search ${props.config.label}`,
        value: props.selected,
        groupBy: (option) => option.groupBy,
        isFilterDirty: props.isFilterDirty,
      },
      active: ![types.categories, types.account, types.labels].includes(props.config.type),
    },
  ];

  const { Component, componentProps } = components.find((component) => component.active);

  const customProps = customPropsCollection[props.config.type]?.() ?? customPropsCollection.defaultFn();

  return (
    <Component data-id={`filterSuggester${props.config.label}`} size="small" {...componentProps} {...customProps} />
  );
}

export const itemPropType = PropTypes.shape({
  label: PropTypes.string,
  value: PropTypes.string,
});

FilterSuggesterComponent.propTypes = {
  config: PropTypes.shape({
    type: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
  }).isRequired,
  selected: PropTypes.arrayOf(itemPropType).isRequired,
  handleClick: PropTypes.func,
  contentOwners: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.shape({})])).isRequired,
  selectAction: PropTypes.func.isRequired,
  isFilterDirty: PropTypes.bool.isRequired,
};

export default FilterSuggesterComponent;
