/**
 * @Move (SQEG)
 * Only used by the TimeTracking module - move to TimeTracking/
 */
import { type ReactNode, useEffect } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { type UseInfiniteQueryResult, type UseQueryResult } from 'react-query';

import { type AxiosResponse } from 'axios';
import {
  IconBuildingSkyscraper,
  IconUserOff,
  IconUsers,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';

import SelectionCard from '@material-hu/components/composed-components/SelectionCard';
import Avatar from '@material-hu/components/design-system/Avatar';
import Pills from '@material-hu/components/design-system/Pills';
import Skeleton from '@material-hu/components/design-system/Skeleton';
import Title from '@material-hu/components/design-system/Title';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useUsersPublicSearch } from 'src/services/usersQueries';
import { type User, UserSelection } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { type PaginatedResponse } from 'src/utils/tableUtils';
import { validateEmployeeManualSelection } from 'src/utils/validation';

import FormEmployeesSelection from 'src/components/FormInputs/FormEmployeesSelection';

type UsersPageResponse = AxiosResponse<PaginatedResponse<User>>;

const FormSelectUsersSkeleton = () => {
  return (
    <Stack sx={{ gap: 2 }}>
      <Skeleton height={76} />
      <Skeleton height={76} />
      <Skeleton height={76} />
    </Stack>
  );
};

type Props = {
  isLoading?: boolean;
  title?: string;
  subtitle?: string;
  customInfiteSearch?: (
    params: Record<string, unknown>,
    extraParams?: Record<string, unknown>,
  ) => UseInfiniteQueryResult<UsersPageResponse>;
  customSearch?: (
    params: Record<string, unknown>,
    extraParams: Record<string, unknown>,
  ) => UseQueryResult<UsersPageResponse>;
  customInfiniteSearchParams?: Record<string, unknown>;
  customSearchParams?: Record<string, unknown>;
  participantsLabel: string;
  searchLabel: string;
  removeNoneOption?: boolean;
  usersFormName?: string;
  slot?: ReactNode;
  translationPrefix?: string | null;
  hasAutomaticAssignment?: boolean;
};

const FormSelectUsers = ({
  isLoading = false,
  subtitle,
  title,
  customInfiteSearch,
  customSearch,
  customInfiniteSearchParams,
  customSearchParams,
  participantsLabel,
  searchLabel,
  removeNoneOption = false,
  usersFormName = 'userIds',
  slot = null,
  translationPrefix = null,
  hasAutomaticAssignment = false,
}: Props) => {
  const { t } = useLokaliseTranslation('audience');
  const HuGoThemeProvider = useHuGoTheme();
  const { watch, resetField, setValue, control, setError, clearErrors } =
    useFormContext();
  const userMode = useWatch({ control, name: 'userMode' });
  const userIds = watch(usersFormName);

  const validateUserMode = (newUserMode: UserSelection) => {
    const validationFn = validateEmployeeManualSelection(userIds);
    Promise.resolve(validationFn(newUserMode)).then(result => {
      if (result === true || result === undefined) {
        clearErrors('userMode');
      } else {
        setError('userMode', {
          type: 'manual',
          message: typeof result === 'string' ? result : undefined,
        });
      }
    });
  };

  const defaultSearchResult = useUsersPublicSearch({
    extraUseQueryParams: { enabled: !customSearch },
  });
  const customSearchResult =
    customSearch?.({ search: '', ...customSearchParams }, { enabled: true }) ||
    null;
  const {
    data: usersData,
    isLoading: isLoadingUsers,
    isFetching: isFetchingUsers,
  } = customSearchResult ?? defaultSearchResult;

  const getTranslationKey = (key: string) =>
    translationPrefix ? `${translationPrefix}.${key}` : key;

  const getIconForSelection = (value: UserSelection) => {
    switch (value) {
      case UserSelection.ALL_USERS:
        return IconBuildingSkyscraper;
      case UserSelection.TARGETED_USERS:
        return IconUsers;
      case UserSelection.NONE:
        return IconUserOff;
    }
  };

  const selectionOptions = Object.values(UserSelection)
    .slice(removeNoneOption ? 1 : 0)
    .map(value => ({
      value,
      label: t(getTranslationKey(value)),
      helperText:
        value === UserSelection.ALL_USERS && hasAutomaticAssignment
          ? t('audience:all_users_description')
          : t(`${getTranslationKey(value)}_info`, {
              count: usersData?.data?.count,
            }),
      icon: getIconForSelection(value),
      chipLabel:
        value === UserSelection.ALL_USERS && hasAutomaticAssignment
          ? t('audience:automatic_assignment')
          : undefined,
    }));

  const customUserSearch =
    customSearch && customInfiteSearch
      ? (searchParams: Record<string, unknown>) =>
          customInfiteSearch({ ...customInfiniteSearchParams, ...searchParams })
      : undefined;

  // biome-ignore lint/correctness/useExhaustiveDependencies: only reset field if userMode changes
  useEffect(() => {
    if (userMode !== UserSelection.TARGETED_USERS) {
      resetField(usersFormName);
    }
  }, [userMode]);

  // biome-ignore lint/correctness/useExhaustiveDependencies: only validate userMode if userMode changes
  useEffect(() => {
    if (userMode) {
      validateUserMode(userMode);
    }
  }, [userIds]);

  if (isLoadingUsers || isFetchingUsers) {
    return <FormSelectUsersSkeleton />;
  }

  return (
    <Stack>
      <HuGoThemeProvider>
        {title && subtitle && (
          <Title
            title={title}
            description={subtitle}
            variant="L"
            sx={{ mb: 4 }}
          />
        )}
        {slot}
        <Stack sx={{ gap: 2 }}>
          {selectionOptions.map(option => {
            const isSelected = userMode === option.value;
            const Icon = option.icon;
            return (
              <SelectionCard
                key={option.value}
                fullWidth
                checked={isSelected}
                disabled={isLoading}
                onClick={() => {
                  setValue('userMode', option.value, {
                    shouldDirty: true,
                    shouldTouch: true,
                    shouldValidate: true,
                  });
                  validateUserMode(option.value);
                }}
                sx={{
                  '& .MuiCardContent-root': {
                    display: 'flex',
                    flexDirection: 'row',
                    gap: 1,
                    alignItems: 'center',
                  },
                }}
              >
                <Avatar Icon={Icon} />
                <Title
                  title={option.label}
                  description={option.helperText}
                  variant="S"
                  sx={{ flex: 1, maxWidth: '90ch' }}
                />
                {option.chipLabel && (
                  <Stack sx={{ marginLeft: 'auto' }}>
                    <Pills
                      label={option.chipLabel}
                      variant="outlined"
                      hasIcon={false}
                      type="highlight"
                    />
                  </Stack>
                )}
              </SelectionCard>
            );
          })}
        </Stack>
      </HuGoThemeProvider>
      {userMode === UserSelection.TARGETED_USERS && (
        <Stack mt={4}>
          <FormEmployeesSelection
            name={usersFormName}
            participantsLabel={participantsLabel}
            searchLabel={searchLabel}
            useCustomUserSearch={customUserSearch}
          />
        </Stack>
      )}
    </Stack>
  );
};

export default FormSelectUsers;
