import { useCallback, useEffect, useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useMutation, useQuery } from 'react-query';

import { type TFunction } from 'i18next';
import { IconInfoCircle } from '@material-hu/icons/tabler';
import { Stack, type Theme, Typography } from '@material-hu/mui/index';

import CollapsibleAutocompleteSelector from '@material-hu/components/composed-components/CollapsibleAutocompleteSelector';
import DatePickerWithOptions from '@material-hu/components/composed-components/DatePickerWithOptions';
import Accordion from '@material-hu/components/design-system/Accordion';
import CardContainer from '@material-hu/components/design-system/CardContainer';
import Drawer from '@material-hu/components/design-system/Drawer';
import FormAutocomplete from '@material-hu/components/design-system/Inputs/Autocomplete/form';
import FormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import Spinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import FormSwitcher from '@material-hu/components/design-system/Switcher/form';
import Title from '@material-hu/components/design-system/Title';
import Tooltip from '@material-hu/components/design-system/Tooltip';

import useGeneralError from 'src/hooks/useGeneralError';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { validateEmailRule } from 'src/utils/validation';

import useSnackbar from '../../hooks/useSnackbar';
import { serviceManagementKeys } from '../../queries';
import { downloadServiceItemReport, getStates } from '../../services';
import {
  type DownloadReportForm as DownloadReportFormType,
  type ServiceItemReportBody,
  type State,
  TaskType,
} from '../../types';
import {
  createStaticOptionsQuery,
  getCreationDateReportFilterDescription,
  getStateName,
  parseReportFormValues,
} from '../../utils';
import { reportFormFields } from '../form/form';
import useAutocompleteReportFields from '../hooks/useAutocompleteReportFields';

const cardStyles = {
  backgroundColor: ({ palette }: Theme) => palette.new.background.elements.grey,
  border: 'unset',
  width: '100%',
};

type Props = {
  open: boolean;
  onClose: () => void;
  serviceItemId: string;
};

const DownloadServiceReportDrawer = ({
  open,
  onClose,
  serviceItemId,
}: Props) => {
  const { t, i18n } = useLokaliseTranslation(['service_management', 'general']);

  const { showSnackbar } = useSnackbar();
  const showGeneralError = useGeneralError();

  const {
    profileFieldOptions,
    isLoadingProfileData,
    isLoadingSegmentations,
    segmentationOptions: segmentationGroupOptions,
  } = useAutocompleteReportFields();

  const {
    reset,
    getValues,
    setValue,
    clearErrors,
    formState: { errors },
  } = useFormContext<DownloadReportFormType>();

  const [
    dateRangeSelected,
    lastSevenDays,
    lastThirtyDays,
    lastSixMonths,
    includeSegmentations,
    includeProfileFields,
    segmentations,
    profileFields,
    createdAtFrom,
    createdAtTo,
  ] = useWatch({
    name: [
      reportFormFields.dateOptions.dateRange(),
      reportFormFields.dateOptions.lastSevenDays(),
      reportFormFields.dateOptions.lastThirtyDays(),
      reportFormFields.dateOptions.lastSixMonths(),
      reportFormFields.includeSegmentations(),
      reportFormFields.includeProfileFields(),
      reportFormFields.segmentations(),
      reportFormFields.profileFields(),
      reportFormFields.createdAtFrom(),
      reportFormFields.createdAtTo(),
    ],
  });

  const downloadMutation = useMutation(
    (body: ServiceItemReportBody) =>
      downloadServiceItemReport(serviceItemId, body),
    {
      onSuccess: (response, values) => {
        if (response.status === 204) {
          showSnackbar({
            title: t('report_download_empty_title'),
            description: t('report_download_empty_description'),
            variant: 'info',
          });
          closeAndReset();
          return;
        }

        showSnackbar({
          title: t('report_download_success_title'),
          description: t('report_download_success_description', {
            email: values.destinationEmails,
          }),
          variant: 'success',
        });
        closeAndReset();
      },
      onError: err => {
        showGeneralError(err, t('report_download_error'));
      },
    },
  );

  const handleDownload = useCallback(() => {
    const values = getValues();
    const parsedValues: ServiceItemReportBody = parseReportFormValues(values);
    downloadMutation.mutate(parsedValues);
  }, [downloadMutation, getValues]);

  const closeAndReset = () => {
    onClose();
    reset();
  };

  const downloadDisabled =
    (includeSegmentations && !segmentations.length) ||
    (includeProfileFields && !profileFields.length) ||
    Object.keys(errors || {}).length > 0;

  const { data: taskStates = [] } = useQuery(
    serviceManagementKeys.states.all(TaskType.INCIDENT),
    () => getStates(TaskType.INCIDENT),
    {
      select: response => response.data,
      refetchOnMount: false,
      refetchOnWindowFocus: false,
    },
  );

  const taskStaticQueryOptions = useMemo(
    () =>
      createStaticOptionsQuery<State>(taskStates, {
        getSearchText: item => t(getStateName(item.name)),
      }),
    [taskStates, t],
  );

  useEffect(() => {
    if (!dateRangeSelected) {
      clearErrors([
        reportFormFields.createdAtFrom(),
        reportFormFields.createdAtTo(),
      ]);
      setValue(reportFormFields.createdAtFrom(), null);
      setValue(reportFormFields.createdAtTo(), null);
    }
  }, [dateRangeSelected, clearErrors, setValue]);

  return (
    <Drawer
      open={open}
      onClose={closeAndReset}
      primaryButtonProps={{
        children: t('general:download'),
        onClick: handleDownload,
        loading: downloadMutation.isLoading,
        disabled: downloadDisabled,
        fullWidth: true,
      }}
      secondaryButtonProps={{
        children: t('clean_selection'),
        onClick: () => reset(),
        disabled: downloadMutation.isLoading,
        fullWidth: true,
      }}
      size="medium"
      title={t('download_report')}
    >
      <Stack
        sx={{
          gap: 2,
        }}
      >
        <Typography variant="globalS">{t('report_form_hint')}</Typography>
        <CardContainer sx={cardStyles}>
          <FormInputClassic
            name={reportFormFields.email()}
            rules={{
              required: { value: true, message: t('required_field') },
              validate: validateEmailRule,
            }}
            inputProps={{
              label: t('report_form_email_label'),
              placeholder: t('report_form_email_placeholder'),
              hasCounter: false,
              sx: {
                '.MuiInputBase-root': {
                  backgroundColor: ({ palette }) =>
                    palette?.hugoBackground?.neutralBgTerciary,
                },
              },
            }}
          />
        </CardContainer>
        <Title
          variant="S"
          title={t('report_form_personalization_title')}
          description={t('report_form_personalization_description')}
        />
        <CardContainer sx={cardStyles}>
          <Stack sx={{ gap: 1.5 }}>
            <FormSwitcher
              name={reportFormFields.includeSegmentations()}
              switcherProps={{
                title: t('report_form_include_segmentations'),
                Icon: (
                  <Tooltip
                    title={t('report_form_include_segmentations_helper_text')}
                  >
                    <IconInfoCircle size={20} />
                  </Tooltip>
                ),
              }}
            />
            {includeSegmentations && (
              <>
                {isLoadingSegmentations && <Spinner />}
                {!isLoadingSegmentations && segmentationGroupOptions && (
                  <FormAutocomplete
                    name={reportFormFields.segmentations()}
                    options={segmentationGroupOptions}
                    autocompleteProps={{
                      isServerFiltered: false,
                      ...(segmentations?.length === 0 && {
                        placeholder: t('select_segmentations'),
                      }),
                      multiple: true,
                      disableCloseOnSelect: true,
                    }}
                  />
                )}
              </>
            )}
          </Stack>
        </CardContainer>
        <CardContainer sx={cardStyles}>
          <Stack sx={{ gap: 1.5 }}>
            <FormSwitcher
              name={reportFormFields.includeProfileFields()}
              switcherProps={{
                title: t('report_form_include_profile_fields'),
                Icon: (
                  <Tooltip
                    title={t('report_form_include_profile_fields_helper_text')}
                  >
                    <IconInfoCircle size={20} />
                  </Tooltip>
                ),
              }}
            />
            {includeProfileFields && (
              <>
                {isLoadingProfileData && <Spinner />}
                {!isLoadingProfileData && profileFieldOptions && (
                  <FormAutocomplete
                    name={reportFormFields.profileFields()}
                    options={profileFieldOptions}
                    autocompleteProps={{
                      isServerFiltered: false,
                      placeholder:
                        profileFields?.length === 0
                          ? t('select_profile_fields')
                          : undefined,
                      multiple: true,
                      disableCloseOnSelect: true,
                    }}
                  />
                )}
              </>
            )}
          </Stack>
        </CardContainer>
        <CollapsibleAutocompleteSelector<State>
          fieldName={reportFormFields.statesIn()}
          sectionTitle={t('task_statuses')}
          customMapper={item => ({
            value: item.id,
            name: t(getStateName(item.name)),
          })}
          infiniteQuery={taskStaticQueryOptions}
          selectAllLabel={t('select_all')}
          noResultsLabel={t('empty_results')}
          lackingOptionsMessage={t('empty_results')}
          formatAndMore={(count: number) => t('and_n_items_more', { count })}
          virtualized
          maxHeight={300}
        />
        <Accordion
          title={t('creation_date')}
          defaultExpanded
          description={getCreationDateReportFilterDescription({
            dateRangeValueSelected: dateRangeSelected,
            lastSevenDays: lastSevenDays,
            lastThirtyDays: lastThirtyDays,
            lastSixMonths: lastSixMonths,
            fromDate: createdAtFrom,
            toDate: createdAtTo,
            language: i18n.language || 'en',
            t: t as TFunction,
          })}
          elevation={0}
          sx={{
            borderRadius: ({ spacing }) => spacing(1),
            backgroundColor: ({ palette }) =>
              palette?.new.background.layout.default,
            '&:before': {
              backgroundColor: 'transparent',
              p: 0,
            },
          }}
          disableGutters
          customDetail={
            <DatePickerWithOptions
              options={[
                {
                  name: reportFormFields.dateOptions.lastSevenDays(),
                  label: t('last_n_days', { days: 7 }),
                },
                {
                  name: reportFormFields.dateOptions.lastThirtyDays(),
                  label: t('last_n_days', { days: 30 }),
                },
                {
                  name: reportFormFields.dateOptions.lastSixMonths(),
                  label: t('last_n_months', { months: 6 }),
                },
                {
                  name: reportFormFields.dateOptions.dateRange(),
                  label: t('choose_date_range'),
                },
              ]}
              showDatePickers
              startDatePicker={{
                name: reportFormFields.createdAtFrom(),
                label: t('general:from'),
                disabled: !dateRangeSelected,
                inputProps: {
                  disableFuture: true,
                },
              }}
              endDatePicker={{
                name: reportFormFields.createdAtTo(),
                label: t('general:until'),
                disabled: !dateRangeSelected,
                inputProps: {
                  disableFuture: true,
                },
              }}
              cardContainerProps={{
                fullWidth: true,
                padding: 16,
              }}
              allowDeselect
            />
          }
        />
      </Stack>
    </Drawer>
  );
};

export default DownloadServiceReportDrawer;
