import { type FC, useEffect } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useQuery } from 'react-query';

import { fromPairs, pickBy } from 'lodash-es';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuFormRadioButtonGroup from '@material-hu/components/composed-components/RadioButtonGroup/form';
import HuStateCard from '@material-hu/components/composed-components/StateCard';
import HuAlert from '@material-hu/components/design-system/Alert';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuFormCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox/form';
import HuDrawer from '@material-hu/components/design-system/Drawer';
import HuCircularProgress from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { FileExtensions } from 'src/constants/filesPreview';
import { useAuth } from 'src/contexts/JWTContext';
import { useDownloadReport } from 'src/hooks/queryHooks/vacations';
import { feedKeys } from 'src/pages/dashboard/feed/queries';
import { profileKeys } from 'src/pages/dashboard/profile/queries';
import AdvanceReportFiltersAccordion from 'src/pages/dashboard/timeOff/components/shared/AdvanceReportFiltersAccordion';
import { getSegmentationGroups } from 'src/services/segmentations';
import { dynamicFieldsResponse } from 'src/services/users';
import {
  ExtensionTypeReport,
  type ReportType,
  TabManagementType,
  type TimeoffAdvancedReportValues,
  type VacationsFilterValues,
} from 'src/types/vacations';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  getAllProfileFields,
  getAllRequestFields,
  getDefaultValuesInAdvancedReport,
  getOptionsSelected,
  putCheckInOptions,
  uncheckAllOptions,
} from 'src/utils/vacations';

export type AdvancedReportProps = {
  open: boolean;
  onClose: () => void;
  reportType: ReportType;
  filters: VacationsFilterValues;
  countRequestManager: number;
  showSendedByEmailModal: () => void;
};

const advancedReport = {
  requestFields: 'requestFields',
  segmentations: 'segmentations',
  profileFields: 'profileFields',
  extensionType: 'extensionType',
  customError: 'customError',
} as const;

const AdvancedReport: FC<AdvancedReportProps> = props => {
  const {
    open,
    onClose,
    reportType,
    filters,
    countRequestManager,
    showSendedByEmailModal,
  } = props;
  const { t } = useLokaliseTranslation('time_off');
  const { enqueueSnackbar } = useHuSnackbar();
  const { user, instance } = useAuth();

  const allRequestFields = getAllRequestFields(reportType, t);

  const form = useForm<TimeoffAdvancedReportValues>({
    defaultValues: getDefaultValuesInAdvancedReport(allRequestFields),
  });

  const {
    reset,
    setError,
    handleSubmit,
    clearErrors,
    formState: { errors },
    formState: { isSubmitting },
  } = form;

  const [requestFields, segmentations, profileFields, extensionType] = useWatch(
    {
      control: form.control,
      name: [
        advancedReport.requestFields,
        advancedReport.segmentations,
        advancedReport.profileFields,
        advancedReport.extensionType,
      ],
    },
  );

  const { data: segmentationGroups = [], isLoading: isLoadingSegmentation } =
    useQuery(feedKeys.segmentate.groups(), () => getSegmentationGroups(), {
      enabled: open,
      select: response => {
        return [
          ...response.data.map(seg => ({
            value: seg.id,
            label: seg.name,
            checked: false,
          })),
        ];
      },
      onError: () => {
        enqueueSnackbar({
          title: t('ERROR_LOADING_SEGMENTATION_GROUPS'),
          variant: 'error',
        });
      },
    });

  const { data: profileDataArray = [], isLoading: isLoadingProfileData } =
    useQuery(
      profileKeys.userProfileData(user!.id, instance!.id),
      () => dynamicFieldsResponse(instance!.id),
      {
        enabled: open,
        select: response => {
          return [
            ...getAllProfileFields(t),
            ...Object.entries(response.data).map(([key, v]) => ({
              value: key,
              label: v.name,
              checked: false,
            })),
          ];
        },
        onSuccess: response => {
          reset(prevValues => ({
            ...prevValues,
            profileFields: putCheckInOptions(response),
          }));
        },
      },
    );

  const handleOnClose = () => {
    onClose();
    reset({
      ...getDefaultValuesInAdvancedReport(
        allRequestFields,
        segmentationGroups,
        profileDataArray,
      ),
    });
  };

  const downloadReportMutation = useDownloadReport(
    filters,
    reportType,
    handleOnClose,
    TabManagementType.MANAGEMENT_TAB_ADVANCED_DOWNLOAD,
    showSendedByEmailModal,
  );

  const clearFilters = () =>
    reset(prevValues => ({
      requestFields: uncheckAllOptions(prevValues.requestFields),
      segmentations: uncheckAllOptions(prevValues.segmentations),
      profileFields: uncheckAllOptions(prevValues.profileFields),
      extensionType: 'XLSX',
      customError: null,
    }));

  const {
    selectedCount: selectedFieldRequestCount,
    allSelected: allRequestFieldsSelected,
    someSelected: someRequestFieldsSelected,
  } = getOptionsSelected(requestFields, allRequestFields);

  const {
    selectedCount: selectedSegmentationsCount,
    allSelected: allSegmentationSelected,
    someSelected: someSegmentationSelected,
  } = getOptionsSelected(segmentations, segmentationGroups);

  const {
    selectedCount: selectedProfileFieldsCount,
    allSelected: allProfileFieldsSelected,
    someSelected: someProfileFieldsSelected,
  } = getOptionsSelected(profileFields, profileDataArray);

  const isSomeOptionSelected =
    !!selectedFieldRequestCount ||
    !!selectedSegmentationsCount ||
    !!selectedProfileFieldsCount;

  useEffect(() => {
    if (isSomeOptionSelected) {
      clearErrors(advancedReport.customError);
    }
  }, [isSomeOptionSelected]);

  const disabledDownloadReport =
    isSubmitting ||
    isLoadingSegmentation ||
    downloadReportMutation.isLoading ||
    isLoadingProfileData;

  const disabledClearSelection =
    isSubmitting ||
    isLoadingSegmentation ||
    downloadReportMutation.isLoading ||
    isLoadingProfileData ||
    !isSomeOptionSelected;

  const handleSelectAll = (
    fieldName:
      | typeof advancedReport.requestFields
      | typeof advancedReport.segmentations
      | typeof advancedReport.profileFields,
    dataArray: Array<{ value: any }>,
    isAllSelected: boolean,
  ) => {
    const availableIds = dataArray.map(item => item.value);

    form.setValue(
      fieldName,
      fromPairs(availableIds.map(id => [id, !isAllSelected])),
    );
  };

  const submit = (values: TimeoffAdvancedReportValues) => {
    if (!isSomeOptionSelected) {
      setError(advancedReport.customError, {
        message: t('error_all_fields_empty'),
      });
      return;
    }

    const extraFields = {
      fields: Object.keys(pickBy(values.requestFields)).toString(),
      groupIds: Object.keys(pickBy(values.segmentations)).toString(),
      userFields: Object.keys(pickBy(values.profileFields)).toString(),
    };

    const data = {
      fileExtension:
        FileExtensions[extensionType as keyof typeof FileExtensions],
      extraFields,
      countRequestManager,
    };

    downloadReportMutation.mutate(data);
  };

  return (
    <FormProvider {...form}>
      <HuDrawer
        anchor="right"
        open={open}
        onClose={handleOnClose}
        title={t('advanced_reports')}
        primaryButtonProps={{
          children: t('download_report'),
          onClick: handleSubmit(submit),
          loading: disabledDownloadReport,
        }}
        secondaryButtonProps={{
          children: t('clean_selection'),
          onClick: clearFilters,
          disabled: disabledClearSelection,
        }}
        footer={
          !errors?.[advancedReport.customError] ? null : (
            <HuAlert
              title={errors?.[advancedReport.customError]?.message!}
              severity="error"
            />
          )
        }
      >
        <Stack sx={{ px: 2, gap: 1 }}>
          <Typography
            variant="globalS"
            sx={{ pb: 2 }}
          >
            {t('advanced_reports_description')}
          </Typography>
          <AdvanceReportFiltersAccordion
            title={t('request_fields')}
            accordionProps={{ defaultExpanded: true }}
          >
            <HuCardContainer sx={{ width: '100%' }}>
              <Stack sx={{ gap: 2 }}>
                <HuFormCheckbox
                  name={'requestFields.ALL'}
                  checkBoxProps={{
                    label: t('select_all'),
                    checked: allRequestFieldsSelected,
                    indeterminate: someRequestFieldsSelected,
                    onChange: () =>
                      handleSelectAll(
                        advancedReport.requestFields,
                        allRequestFields,
                        allRequestFieldsSelected,
                      ),
                  }}
                />
                {allRequestFields.map(requestField => (
                  <HuFormCheckbox
                    name={`requestFields.${requestField.value}`}
                    key={requestField.value}
                    checkBoxProps={{
                      label: requestField.label,
                    }}
                  />
                ))}
              </Stack>
            </HuCardContainer>
          </AdvanceReportFiltersAccordion>
          <AdvanceReportFiltersAccordion title={t('segmentation')}>
            {isLoadingSegmentation && <HuCircularProgress />}
            {!isLoadingSegmentation && segmentationGroups.length === 0 && (
              <HuStateCard
                sx={{ width: '100%', border: 'none' }}
                slotProps={{
                  title: {
                    title: t('no_results'),
                  },
                }}
              />
            )}
            {segmentationGroups.length > 0 && !isLoadingSegmentation && (
              <HuCardContainer sx={{ width: '100%' }}>
                <Stack sx={{ gap: 2 }}>
                  <HuFormCheckbox
                    name={'segmentations.ALL'}
                    checkBoxProps={{
                      label: t('select_all'),
                      checked: allSegmentationSelected,
                      indeterminate: someSegmentationSelected,
                      onChange: () =>
                        handleSelectAll(
                          advancedReport.segmentations,
                          segmentationGroups,
                          allSegmentationSelected,
                        ),
                    }}
                  />
                  {segmentationGroups.map(segmentation => (
                    <HuFormCheckbox
                      key={segmentation.value}
                      name={`segmentations.${segmentation.value}`}
                      checkBoxProps={{
                        label: segmentation.label,
                      }}
                    />
                  ))}
                </Stack>
              </HuCardContainer>
            )}
          </AdvanceReportFiltersAccordion>
          <AdvanceReportFiltersAccordion title={t('profile_fields')}>
            {isLoadingProfileData && <HuCircularProgress />}
            {!isLoadingProfileData && profileDataArray.length === 0 && (
              <HuStateCard
                sx={{ width: '100%', border: 'none' }}
                slotProps={{
                  title: {
                    title: t('no_results'),
                  },
                }}
              />
            )}
            {profileDataArray.length > 0 && !isLoadingProfileData && (
              <HuCardContainer sx={{ width: '100%' }}>
                <Stack sx={{ gap: 2 }}>
                  <HuFormCheckbox
                    name="profileFields.ALL"
                    checkBoxProps={{
                      label: t('select_all'),
                      checked: allProfileFieldsSelected,
                      indeterminate: someProfileFieldsSelected,
                      onChange: () =>
                        handleSelectAll(
                          advancedReport.profileFields,
                          profileDataArray,
                          allProfileFieldsSelected,
                        ),
                    }}
                  />
                  {profileDataArray.map(pf => (
                    <HuFormCheckbox
                      name={`profileFields.${pf.value}`}
                      key={pf.value}
                      checkBoxProps={{
                        label: pf.label,
                      }}
                    />
                  ))}
                </Stack>
              </HuCardContainer>
            )}
          </AdvanceReportFiltersAccordion>
          <Stack sx={{ py: 1, gap: 1 }}>
            <Typography
              variant="globalS"
              fontWeight="fontWeightSemiBold"
            >
              {t('format_selection')}
            </Typography>
            <HuFormRadioButtonGroup
              name={advancedReport.extensionType}
              sx={{ gap: 1 }}
              options={Object.keys(ExtensionTypeReport).map(value => ({
                label: t(`download_in_${value}`),
                value,
              }))}
            />
          </Stack>
        </Stack>
      </HuDrawer>
    </FormProvider>
  );
};

export default AdvancedReport;
