import { useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';

import Audience from '@material-hu/components/composed-components/audience/Audience';
import {
  type AudienceFormValues,
  type CriteriaEntry,
  CriteriaType,
  type IndividualCriteriaEntry,
} from '@material-hu/components/composed-components/audience/Audience/types';

import { infiniteQueryDataParser } from 'src/utils/pagination';

import useAudienceFormCount from 'src/components/Audience/hooks/useAudienceFormCount';
import useGetAudienceUsers from 'src/components/Audience/hooks/useGetAudienceUsers';
import useSegmentationFieldItems from 'src/components/Audience/hooks/useSegmentationFieldItems';
import useSegmentationValueItems from 'src/components/Audience/hooks/useSegmentationValueItems';
import useSelectedUsers from 'src/components/Audience/hooks/useSelectedUsers';
import { criteriasToSegmentationExpression } from 'src/components/Audience/utils/criteriasToSegmentationExpression';
import {
  getIndividualDescription,
  getSegmentationDescription,
} from 'src/components/Audience/utils/descriptions';
import { getCollaboratorsService } from 'src/components/Audience/utils/getCollaboratorsService';

import {
  AVAILABLE_CRITERIA_TYPES,
  individualCollaboratorsReach,
  SELECTED_REACH_KEY,
  segmentationCollaboratorsReach,
} from './constants';

type CalibrationAudienceProps = {
  title: string;
  description: string;
};

const CalibrationAudience = ({
  title,
  description,
}: CalibrationAudienceProps) => {
  const { control } = useFormContext<AudienceFormValues>();
  const criterias = useWatch({ control, name: 'criterias' }) ?? [];

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

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

  const selectedUserIds = useMemo(() => {
    const ids: number[] = [];
    criterias.forEach((criteria: CriteriaEntry) => {
      if (criteria.type === CriteriaType.INDIVIDUAL) {
        ids.push(...[...criteria.userIds].map(Number));
      }
    });
    return ids;
  }, [criterias]);

  const userNamesMap = useSelectedUsers(selectedUserIds);

  const handleGetIndividualDescription = (entry: IndividualCriteriaEntry) =>
    getIndividualDescription(entry, userNamesMap);

  return (
    <Audience
      title={title}
      description={description}
      availableCriteriaTypes={AVAILABLE_CRITERIA_TYPES}
      segmentationDrawerProps={{
        collaboratorsReach: segmentationCollaboratorsReach,
        inputProps: {
          dynamicItems: {
            useFieldItems: useSegmentationFieldItems,
            useValueItems: useSegmentationValueItems,
          },
        },
      }}
      individualDrawerProps={{
        inputProps: {
          useUsersQuery: useGetAudienceUsers,
          usersQueryDataParser: infiniteQueryDataParser,
        },
        collaboratorsReach: individualCollaboratorsReach,
      }}
      selectedCollaboratorsDrawerProps={{
        service: collaboratorsService,
        queryKey: SELECTED_REACH_KEY,
      }}
      getSegmentationDescription={getSegmentationDescription}
      getIndividualDescription={handleGetIndividualDescription}
      useCount={useAudienceFormCount}
    />
  );
};

export default CalibrationAudience;
