import { FiltersMap } from '@wix/bex-core';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import React, { useCallback } from 'react';
import {
  AccordionProps,
  Box,
  accordionSectionItemBuilder,
} from '@wix/design-system';
import { CollectionFilter } from '../components/CollectionFilter';
import { FilterElement } from '../components/CollectionToolbarFilters';
import { CollectionToolbarFiltersState } from '../components/CollectionToolbarFilters/CollectionToolbarFiltersState';
import { FilterAccordionResetButton } from '../components/FiltersPanel/FilterAccordionResetButton';
import { FilterAccordionTitle } from '../components/FiltersPanel/FilterAccordionTitle';
import { getFieldTypeIcon } from '../utils/fieldTypePrefixIcons';

function useBuildAccordionItem<T, F extends FiltersMap>(
  state: CollectionToolbarFiltersState<T, F>,
  showFieldTypeIcons: boolean,
) {
  return useCallback(
    (filterElement: FilterElement) => {
      const { type: Component, props: filterProps } = filterElement;
      const {
        filter,
        initiallyOpen,
        popoverProps,
        accordionItemProps,
        fieldType,
      } = filterProps;

      const clonedElement = (
        <Component
          {...filterProps}
          popoverProps={{ appendTo: 'window', ...popoverProps }}
        />
      );
      const titleElement = (
        <FilterAccordionTitle
          state={state.toolbar}
          filter={filter}
          filterProps={filterProps}
        />
      );
      const titleWithIcon = showFieldTypeIcons ? (
        <Box gap="SP1" verticalAlign="middle">
          {getFieldTypeIcon({ fieldType, size: 'medium' })}
          {titleElement}
        </Box>
      ) : (
        titleElement
      );

      const title = filterProps.filter ? (
        <Box width="100%" align="space-between" verticalAlign="middle">
          {titleWithIcon}
          <FilterAccordionResetButton
            state={state.toolbar}
            filter={filterProps.filter}
          />
        </Box>
      ) : (
        titleWithIcon
      );

      return {
        title,
        children: filterProps.filter ? (
          <CollectionFilter filter={filterProps.filter} state={state}>
            {clonedElement}
          </CollectionFilter>
        ) : (
          clonedElement
        ),
        initiallyOpen,
        ...accordionItemProps,
      };
    },
    [showFieldTypeIcons],
  );
}

export function useBuildAccordionItems<T, F extends FiltersMap>(
  state: CollectionToolbarFiltersState<T, F>,
  searchTerm: string = '',
) {
  const { translate: t } = useWixPatternsContainer();
  const { panelFilterElements } = state;
  const showFieldTypeIcons = state.toolbar.showFieldTypeIcons;
  const buildAccordionItem = useBuildAccordionItem(state, showFieldTypeIcons);

  const defaultSectionTitle = t('cairo.filtersPanel.sections.default.title');

  const term = searchTerm.trim().toLowerCase();
  const elements = term
    ? panelFilterElements.filter((el) => {
        const label = (el.props?.accordionItemProps?.label ?? '').toLowerCase();
        const section = (el.props?.sectionTitle ?? '').toLowerCase();
        return label.includes(term) || section.includes(term);
      })
    : panelFilterElements;

  const { groups, defaultGroup } = elements.reduce<{
    groups: Record<string, NonNullable<AccordionProps['items']>>;
    defaultGroup: NonNullable<AccordionProps['items']>;
  }>(
    (accumulator, item) => {
      const sectionTitle = item.props?.sectionTitle;

      if (!sectionTitle) {
        return {
          ...accumulator,
          defaultGroup: [...accumulator.defaultGroup, buildAccordionItem(item)],
        };
      }

      const groupItems = accumulator.groups[sectionTitle]
        ? [...accumulator.groups[sectionTitle], buildAccordionItem(item)]
        : [
            accordionSectionItemBuilder({ title: sectionTitle }),
            buildAccordionItem(item),
          ];

      return {
        ...accumulator,
        groups: {
          ...accumulator.groups,
          [sectionTitle]: groupItems,
        },
      };
    },
    {
      groups: {},
      defaultGroup: [],
    },
  );

  const items = Object.values(groups).flat();

  if (!items.length) {
    return defaultGroup;
  }

  return [
    ...items,
    ...(defaultGroup.length
      ? [
          accordionSectionItemBuilder({ title: defaultSectionTitle }),
          ...defaultGroup,
        ]
      : []),
  ];
}
