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

import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

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 FormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';

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 { downloadServiceItemCertificate, getStates } from '../../services';
import {
  type DownloadCertificatesForm,
  type ServiceItemCertificateBody,
  type State,
  TaskType,
} from '../../types';
import {
  createStaticOptionsQuery,
  getCreationDateReportFilterDescription,
  getStateName,
  parseCertificateFormValues,
} from '../../utils';
import { certificatesFormFields } from '../form/form';

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

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

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

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

  const [
    dateRangeSelected,
    lastSevenDays,
    lastThirtyDays,
    lastSixMonths,
    createdAtFrom,
    createdAtTo,
  ] = useWatch({
    name: [
      certificatesFormFields.dateOptions.dateRange(),
      certificatesFormFields.dateOptions.lastSevenDays(),
      certificatesFormFields.dateOptions.lastThirtyDays(),
      certificatesFormFields.dateOptions.lastSixMonths(),
      certificatesFormFields.createdAtFrom(),
      certificatesFormFields.createdAtTo(),
    ],
  });

  const downloadMutation = useMutation(
    (body: ServiceItemCertificateBody) =>
      downloadServiceItemCertificate(serviceItemId, body),
    {
      onSuccess: (response, values) => {
        if (response.status === 204) {
          showSnackbar({
            title: t('download_certificate.warning_email_title'),
            description: t('download_certificate.warning_email_description', {
              email: values.destinationEmail,
            }),
            variant: 'warning',
          });
        } else {
          showSnackbar({
            title: t('download_certificate.success_email_title'),
            description: t('download_certificate.success_email_description', {
              email: values.destinationEmail,
            }),
            variant: 'success',
          });
        }
        closeAndReset();
      },
      onError: err => {
        showGeneralError(err, t('download_certificate.error_title'));
      },
    },
  );

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

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

  const downloadDisabled = 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([
        certificatesFormFields.createdAtFrom(),
        certificatesFormFields.createdAtTo(),
      ]);
      setValue(certificatesFormFields.createdAtFrom(), null);
      setValue(certificatesFormFields.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_certificate.title')}
    >
      <Stack
        sx={{
          gap: 2,
        }}
      >
        <Typography variant="globalS">
          {t('download_certificate.admin_hint')}
        </Typography>
        <CardContainer
          fullWidth
          color="grey"
          sx={{
            border: 'none',
          }}
        >
          <FormInputClassic
            name={certificatesFormFields.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?.new.background.layout.tertiary,
                },
              },
            }}
          />
        </CardContainer>
        <CollapsibleAutocompleteSelector<State>
          fieldName={certificatesFormFields.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.elements.grey,
            '&:before': {
              backgroundColor: 'transparent',
              p: 0,
            },
          }}
          disableGutters
          customDetail={
            <DatePickerWithOptions
              options={[
                {
                  name: certificatesFormFields.dateOptions.lastSevenDays(),
                  label: t('last_n_days', { days: 7 }),
                },
                {
                  name: certificatesFormFields.dateOptions.lastThirtyDays(),
                  label: t('last_n_days', { days: 30 }),
                },
                {
                  name: certificatesFormFields.dateOptions.lastSixMonths(),
                  label: t('last_n_months', { months: 6 }),
                },
                {
                  name: certificatesFormFields.dateOptions.dateRange(),
                  label: t('choose_date_range'),
                },
              ]}
              showDatePickers
              startDatePicker={{
                name: certificatesFormFields.createdAtFrom(),
                label: t('general:from'),
                disabled: !dateRangeSelected,
                inputProps: {
                  disableFuture: true,
                },
              }}
              endDatePicker={{
                name: certificatesFormFields.createdAtTo(),
                label: t('general:until'),
                disabled: !dateRangeSelected,
                inputProps: {
                  disableFuture: true,
                },
              }}
              cardContainerProps={{
                fullWidth: true,
                padding: 16,
              }}
              allowDeselect
            />
          }
        />
      </Stack>
    </Drawer>
  );
};

export default DownloadServiceCertificateDrawer;
