import { lazy, Suspense, useCallback, useMemo } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import { GetDrawerConfiguration } from '@material-hu/hooks/useDrawerV2';
import { useModal } from '@material-hu/hooks/useModal';

import useAuth from 'src/contexts/JWTContext';
import useProfileFields from 'src/hooks/queryHooks/useProfileFields';
import useSegmentationGroups from 'src/hooks/queryHooks/useSegmentationGroups';
import useUsers from 'src/hooks/queryHooks/useUsers';
import { useUsersReport } from 'src/hooks/queryHooks/useUsersReport';
import { ApiErrorCode } from 'src/types/apiErrorCodes';
import { UsersReportTypes } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { parseBlobError } from 'src/utils/server';

import DownloadingModal from 'src/components/DownloadingModal';
import { UserFields } from 'src/components/ReportFilter/constants';

const DownloadUsersDrawer = lazy(
  () => import('../components/DownloadUsersDrawer'),
);

type FormValues = {
  type: UsersReportTypes;
  includeGroups: boolean;
  includedGroups: number[];
  includeUserFields: boolean;
  userFields: string[];
  email: string | null;
};

type GetDownloadUsersDrawerContentArgs = Record<string, never>;

/**
 * Custom hook to manage the Download Users drawer content and form logic
 * Handles form state, submission, and error management
 */
export const useDownloadUsersDrawerContent: GetDrawerConfiguration<
  GetDownloadUsersDrawerContentArgs
> = args => {
  const { t } = useLokaliseTranslation('users');
  const { user } = useAuth();

  const { data: sendByEmail } = useUsers(
    { page: 0, limit: 1 },
    {
      enabled: args.open,
      select: r => r.data.count >= 1000,
    },
  );

  const form = useForm<FormValues>({
    defaultValues: {
      type: UsersReportTypes.FULL_REPORT,
      includeGroups: false,
      includedGroups: [],
      includeUserFields: false,
      userFields: [],
      email: user?.email || '',
    },
    reValidateMode: 'onChange',
  });

  const {
    formState: { isValid, submitCount },
    handleSubmit,
  } = form;

  const {
    modal: downloadingModal,
    showModal: showDownloadingModal,
    closeModal: closeDownloadingModal,
  } = useModal(DownloadingModal, { maxWidth: 'sm', fullWidth: true });

  const { mutate: getUsersReport, isLoading: isDownloading } =
    useUsersReport(form);

  const selectProfileFields = useCallback(
    (response: any) => [
      ...Object.values(UserFields).map(id => ({
        id,
        name: t(id === 'JOB_POSITION' ? 'POSITION' : `USER_FIELDS.${id}`),
      })),
      { id: 'REVIEWER', name: t('reviewer') },
      ...response.data,
    ],
    [t],
  );

  const { data: profileFields = [], isLoading: profileFieldsLoading } =
    useProfileFields({
      enabled: args.open,
      select: selectProfileFields,
    });

  const { data: segmentationQuery = [], isLoading: segmentationQueryLoading } =
    useSegmentationGroups({
      enabled: args.open,
    });

  const handleClose = useCallback(() => {
    closeDownloadingModal();
    form.reset();
    args.closeDrawer();
  }, [closeDownloadingModal, form, args]);

  const handleDownloadExcel = useCallback(
    async (values: FormValues) => {
      showDownloadingModal();
      getUsersReport(
        { ...values, email: undefined },
        {
          onSuccess: () => closeDownloadingModal(),
          onError: async error => {
            const errorData = await parseBlobError(error);
            const errorCode = errorData?.code;

            if (errorCode !== ApiErrorCode.DOMAIN_NOT_ALLOWED_TO_SEND_REPORT) {
              closeDownloadingModal();
            }
          },
        },
      );
    },
    [showDownloadingModal, getUsersReport, closeDownloadingModal],
  );

  const submit = useCallback(
    handleSubmit(async values => {
      if (sendByEmail) {
        getUsersReport(
          { ...values, email: values.email },
          {
            onSuccess: () => handleClose(),
            onError: async error => {
              const errorData = await parseBlobError(error);
              const errorCode = errorData?.code;

              if (
                errorCode !== ApiErrorCode.DOMAIN_NOT_ALLOWED_TO_SEND_REPORT
              ) {
                handleClose();
              }
            },
          },
        );
      } else {
        await handleDownloadExcel(values);
        handleClose();
      }
    }),
    [
      handleSubmit,
      sendByEmail,
      getUsersReport,
      handleClose,
      handleDownloadExcel,
    ],
  );

  const options = useMemo(
    () => [
      { label: t('ALL_USERS'), value: UsersReportTypes.FULL_REPORT },
      { label: t('USERS_ACTIVE_USERS'), value: UsersReportTypes.ACTIVE_REPORT },
      { label: t('UNCLAIMED'), value: UsersReportTypes.UNCLAIMED_REPORT },
      { label: t('DEACTIVATED'), value: UsersReportTypes.DEACTIVATED_REPORT },
    ],
    [t],
  );

  return {
    title: t('DOWNLOAD'),
    children: (
      <Suspense fallback={null}>
        <FormProvider {...form}>
          {downloadingModal}
          <DownloadUsersDrawer
            options={options}
            profileFields={profileFields}
            segmentationQuery={segmentationQuery}
            sendByEmail={sendByEmail}
            isLoading={segmentationQueryLoading || profileFieldsLoading}
          />
        </FormProvider>
      </Suspense>
    ),
    primaryButtonProps: {
      children: t(sendByEmail ? 'GENERAL:SEND' : 'DOWNLOAD'),
      onClick: submit,
      disabled: isDownloading || (submitCount > 0 && !isValid),
      loading: isDownloading,
      fullWidth: true,
    },
    secondaryButtonProps: {
      children: t('CANCEL'),
      onClick: handleClose,
      fullWidth: true,
    },
    onClose: handleClose,
  };
};
