import { useMemo, useRef } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';

import { isEqual } from 'lodash';
import Stack from '@material-hu/mui/Stack';

import Audience from '@material-hu/components/composed-components/audience/Audience';
import {
  type CriteriaEntry,
  CriteriaType,
} from '@material-hu/components/composed-components/audience/Audience/types';
import HuTitle from '@material-hu/components/design-system/Title';

import { queryClient } from 'src/config/react-query';
import { updateSegmentation } from 'src/pages/dashboard/PeopleExperience/services';
import { useInfiniteUsersPublicSearch } from 'src/services/usersQueries';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { infiniteQueryDataParser } from 'src/utils/pagination';

import useAudienceFormCount from 'src/components/Audience/hooks/useAudienceFormCount';
import useIndividualDrawerService from 'src/components/Audience/hooks/useIndividualDrawerService';
import { criteriasToSegmentationExpression } from 'src/components/Audience/utils/criteriasToSegmentationExpression';
import { getCollaboratorsService } from 'src/components/Audience/utils/getCollaboratorsService';

import { pxKeys } from '../../../queries';
import { MAX_CONTENT_WIDTH } from '../../constants';
import StepLayout from '../StepLayout';

import useIndividualPxCount from './hooks/useIndividualPxCount';
import useSegmentFilter from './hooks/useSegmentFilter';
import { type ParticipantStepProps } from './types';
import { criteriasToUserIds, surveyToCriterias } from './utils';

type FormValues = { criterias: CriteriaEntry[] };

const ParticipantStep = ({
  onBack,
  onNext,
  initialParticipants,
  surveyId,
}: ParticipantStepProps) => {
  const { t } = useLokaliseTranslation(['people_experience', 'general']);

  const form = useForm<FormValues>({
    defaultValues: { criterias: surveyToCriterias(initialParticipants) },
  });

  const criterias = form.watch('criterias');

  const { mutate: updateParticipants, isLoading: isUpdatingParticipants } =
    useMutation(
      ({ userIds }: { userIds: number[] }) =>
        updateSegmentation({ surveyId, userIds }),
      {
        onSuccess: () => {
          queryClient.invalidateQueries(pxKeys.surveyDetail(surveyId));
          onNext();
        },
      },
    );

  const onSubmit = ({ criterias: c }: FormValues) => {
    const userIds = criteriasToUserIds(c);
    const sortedInitial = [...new Set(initialParticipants ?? [])].sort();
    const sortedNext = [...new Set(userIds)].sort();
    if (initialParticipants !== null && isEqual(sortedInitial, sortedNext)) {
      onNext();
      return;
    }
    updateParticipants({ userIds });
  };

  const { segmentationItemIds, filterCount, filterButtonOnClick } =
    useSegmentFilter();

  const segmentationItemIdsRef = useRef(segmentationItemIds);
  segmentationItemIdsRef.current = segmentationItemIds;

  const useUsersQuery = (search: string) =>
    useInfiniteUsersPublicSearch({
      search,
      segmentationItemIds: segmentationItemIdsRef.current,
    });

  const collaboratorsService = useMemo(
    () => getCollaboratorsService(criteriasToSegmentationExpression(criterias)),
    [criterias],
  );

  return (
    <FormProvider {...form}>
      <StepLayout
        onNext={form.handleSubmit(onSubmit)}
        onBack={onBack}
        slotProps={{
          submitButton: { loading: isUpdatingParticipants },
        }}
      >
        <Stack
          sx={{
            width: '100%',
            alignItems: 'center',
            gap: 4,
            height: '100%',
            p: 4,
            overflowY: 'auto',
            backgroundColor: theme =>
              theme.palette.new.background.layout.tertiary,
          }}
        >
          <Stack sx={{ width: '100%', maxWidth: MAX_CONTENT_WIDTH }}>
            <Audience
              title={t('select_participants')}
              description=""
              availableCriteriaTypes={[
                CriteriaType.ALL,
                CriteriaType.INDIVIDUAL,
              ]}
              individualDrawerProps={{
                inputProps: {
                  useUsersQuery,
                  filterCount,
                  usersQueryDataParser: infiniteQueryDataParser,
                  slotProps: {
                    filterButton: {
                      onClick: filterButtonOnClick,
                      children: t('general:filter'),
                    },
                  },
                },
                collaboratorsReach: {
                  useCount: useIndividualPxCount,
                  useService: useIndividualDrawerService,
                  queryKey: pxKeys
                    .individualDrawerCollaborators(surveyId)
                    .join('.'),
                },
              }}
              segmentationDrawerProps={{ inputProps: {} }}
              selectedCollaboratorsDrawerProps={{
                service: collaboratorsService,
                queryKey: pxKeys.participantCollaborators(surveyId).join('.'),
              }}
              useCount={useAudienceFormCount}
              getIndividualDescription={entry =>
                t('employee_count', { count: entry.userIds.size })
              }
              getSegmentationDescription={() => ''}
              showAllSelectedAlert={false}
            />
          </Stack>
        </Stack>
      </StepLayout>
    </FormProvider>
  );
};

export default ParticipantStep;
