import { useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import { IconZoomExclamation } from '@material-hu/icons/tabler';
import FormHelperText from '@material-hu/mui/FormHelperText';
import Stack from '@material-hu/mui/Stack';

import Search from '@material-hu/components/design-system/Inputs/Search';
import Skeleton from '@material-hu/components/design-system/Skeleton';
import StateCard from '@material-hu/components/design-system/StateCard';
import Title from '@material-hu/components/design-system/Title';

import {
  appearFromBottom,
  DEFAULT_ANIMATION_DELAY,
} from 'src/constants/animation';
import useSegmentationGroups from 'src/hooks/queryHooks/useSegmentationGroups';
import { useLokaliseTranslation } from 'src/utils/i18n';

import SegmentationGroupList from './components/SegmentationGroupList';
import { type FormSegmentationGroupSelectorProps } from './types';

// TODO: Replace with @material-hu/components/composed-components/audience/SegmentationGroupItemsSelection
const FormSegmentationGroupSelector = ({
  name,
  rules,
  excludedGroupsIds = [],
  allowSelectAll = true,
  showHeader = true,
  withUsersCount = false,
  useAudienceApi = false,
  queryOptions,
  returnAsObject = false,
  sx,
  slotProps,
}: FormSegmentationGroupSelectorProps) => {
  const { t } = useLokaliseTranslation(['backoffice_only']);
  const [search, setSearch] = useState('');
  const { control } = useFormContext();

  const {
    data: segmentationGroups = [],
    isLoading: segmentationGroupsIsLoading,
  } = useSegmentationGroups(
    {
      select: r => r.data,
      ...queryOptions,
    },
    withUsersCount,
    useAudienceApi,
  );

  // filter out excluded items and empty groups
  const filteredSegmentationGroups = segmentationGroups
    .map(group => ({
      ...group,
      items: group.items.filter(item => !excludedGroupsIds.includes(item.id)),
    }))
    .filter(
      ({ items, name: groupName }) =>
        items.length &&
        groupName.toLocaleLowerCase().includes(search.toLowerCase()),
    );

  if (segmentationGroupsIsLoading) {
    return (
      <>
        <Title
          variant="M"
          title={t(
            'backoffice_only:form_segmentation_group_selector.form_segmentation_group_selector__segmentation_groups',
          )}
        />
        <Search
          value={search}
          onChange={setSearch}
          disabled
        />
        <Stack sx={{ gap: 2 }}>
          <Skeleton sx={{ height: 54 }} />
          <Skeleton sx={{ height: 54 }} />
          <Skeleton sx={{ height: 54 }} />
        </Stack>
      </>
    );
  }

  return (
    <Controller
      control={control}
      name={name}
      rules={rules}
      render={({ field: { ref, ...field }, fieldState: { error } }) => (
        <Stack sx={{ gap: 2, ...sx }}>
          {showHeader && (
            <>
              <Title
                variant="M"
                title={t(
                  'backoffice_only:form_segmentation_group_selector.form_segmentation_group_selector__segmentation_groups',
                )}
              />
              <Search
                value={search}
                onChange={setSearch}
              />
            </>
          )}

          {!filteredSegmentationGroups.length && !!search && (
            <StateCard
              sx={{ border: 'none' }}
              icon={IconZoomExclamation}
              title={t(
                'backoffice_only:form_segmentation_group_selector.form_segmentation_group_selector__no_search_results_title',
              )}
              description={t(
                'backoffice_only:form_segmentation_group_selector.form_segmentation_group_selector__no_search_results_description',
              )}
            />
          )}
          {filteredSegmentationGroups.flatMap((segmentationGroup, index) => {
            const currentSelectionSet = new Set<number>(
              returnAsObject
                ? field.value?.[segmentationGroup.id] || []
                : field.value,
            );

            return (
              <SegmentationGroupList
                key={segmentationGroup.id}
                selected={currentSelectionSet}
                items={segmentationGroup.items}
                name={segmentationGroup.name}
                onChange={value => {
                  if (returnAsObject) {
                    field.onChange({
                      ...field.value,
                      [segmentationGroup.id]: value,
                    });
                  } else {
                    field.onChange(value);
                  }
                }}
                allowSelectAll={allowSelectAll}
                sx={{
                  animation: `${appearFromBottom} 0.1s ease-in-out backwards`,
                  animationDelay: `${DEFAULT_ANIMATION_DELAY * index}s`,
                  ...slotProps?.segmentationGroupList?.sx,
                }}
                slotProps={slotProps?.segmentationGroupList?.slotProps}
              />
            );
          })}
          {error && <FormHelperText error>{error?.message}</FormHelperText>}
        </Stack>
      )}
    />
  );
};

export default FormSegmentationGroupSelector;
