import { useCallback, useMemo, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { FormProvider, useForm } from 'react-hook-form';

import { yupResolver } from '@hookform/resolvers/yup';
import {
  IconChevronDown,
  IconDownload,
  IconFilter,
} from '@material-hu/icons/tabler';
import Container from '@material-hu/mui/Container';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuFormCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox/form';
import HuMenu from '@material-hu/components/design-system/Menu';
import HuMenuItem from '@material-hu/components/design-system/Menu/components/MenuItem';
import StateCard from '@material-hu/components/design-system/StateCard';
import HuTitle from '@material-hu/components/design-system/Title';

import useAuth from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import BadgeCountButton from '../AgentManagement/components/BadgeCountButton';
import ActivateModuleCard from '../components/ActivateModuleCard';
import useModuleConfiguration from '../hooks/useModuleConfiguration';
import useServiceMgmtPermissions from '../hooks/useServiceMgmtPermissions';
import {
  type DownloadCsatReportForm,
  type MetricFiltersForm,
  type RatingForm,
} from '../types';
import { getDefaultEmail } from '../utils';

import CsatChart from './components/CsatChart';
import CsatTable from './components/CsatTable';
import DownloadCsatReportDrawer from './components/DownloadCsatReportDrawer';
import InfoCard from './components/InfoCard';
import MetricFiltersControls from './components/MetricFiltersControls';
import MetricFiltersDrawer from './components/MetricFiltersDrawer';
import ServiceItemsStateChart from './components/ServiceItemsStateChart';
import { metricFilterFields } from './form/form';
import {
  createCsatReportSchema,
  createMetricFiltersSchema,
} from './form/yupSchemas';
import useMetrics from './hooks/useMetrics';

const EMPTY_FILTERS: MetricFiltersForm = {
  startDate: null,
  endDate: null,
  dateOptions: {
    lastSevenDays: false,
    lastFourteenDays: false,
    lastThirtyDays: false,
    dateRange: false,
  },
  serviceItems: [],
};

export const DEFAULT_FILTERS: MetricFiltersForm = {
  startDate: null,
  endDate: null,
  dateOptions: {
    lastSevenDays: false,
    lastFourteenDays: false,
    lastThirtyDays: true,
    dateRange: false,
  },
  serviceItems: [],
};

export const DEFAULT_REPORT_FORM_VALUES: Omit<DownloadCsatReportForm, 'email'> =
  {
    includeServiceItems: false,
    serviceItems: [],
    dateOptions: {
      lastSevenDays: false,
      lastFourteenDays: false,
      lastThirtyDays: false,
      dateRange: false,
    },
    startDate: null,
    endDate: null,
  };

const MINIMUM_RESPONSES_TO_SHOW = 3;

const Metrics = () => {
  const { t } = useLokaliseTranslation(['service_management', 'general']);
  const { user } = useAuth();
  const theme = useTheme();
  const HuGoThemeProvider = useHuGoTheme();

  const { canDownloadCsatReport } = useServiceMgmtPermissions();
  const { moduleConfiguration, moduleActivated, isLoadingModuleConfiguration } =
    useModuleConfiguration();

  const [filtersDrawerOpen, setFiltersDrawerOpen] = useState(false);
  const [downloadCsatReportDrawerOpen, setDownloadCsatReportDrawerOpen] =
    useState(false);
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const open = Boolean(anchorEl);

  const form = useForm<MetricFiltersForm>({
    defaultValues: DEFAULT_FILTERS,
    resolver: yupResolver(createMetricFiltersSchema(t)),
    mode: 'onChange',
  });

  const downloadReportForm = useForm<DownloadCsatReportForm>({
    defaultValues: {
      email: getDefaultEmail(user),
      ...DEFAULT_REPORT_FORM_VALUES,
    },
    resolver: yupResolver(createCsatReportSchema(t)),
    mode: 'onChange',
  });

  const ratingForm = useForm<RatingForm>({
    defaultValues: {
      '1': false,
      '2': false,
      '3': false,
      '4': false,
      '5': false,
    },
  });

  const {
    updateAppliedFilters,
    appliedFilters,
    selectedDates,
    setSelectedDates,
    // Tasks
    tasksChartData,
    tasksMetrics,
    isTasksError,
    isTasksLoading,
    refetchTaskData,
    // CSAT
    csatMetrics,
    csatChartData,
    isCsatError,
    isCsatLoading,
    refetchCsatData,
    isCsatRefetching,
    // CSAT Responses (Table)
    csatTableData,
    isLoadingTableData,
    isErrorTableData,
    refetchTableData,
    isRefetchingTableData,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    setAppliedRatings,
    appliedRatings,
  } = useMetrics();

  const requestsCount = tasksMetrics?.totalTasks || 0;
  const activeServiceItemsCount = tasksMetrics?.activeCatalogItems;
  const averageCsatRating = csatMetrics?.averageRating || 0;
  const totalCsatResponses = csatMetrics?.totalCsatResponse || 0;
  const appliedRatingsCount = appliedRatings.length;

  const handleConfirmFilters = () => {
    const formValues = form.getValues();
    updateAppliedFilters(formValues);
    setFiltersDrawerOpen(false);
  };

  const handleCleanFilters = () => {
    form.reset({
      ...DEFAULT_FILTERS,
      dateOptions: {
        ...DEFAULT_FILTERS.dateOptions,
        lastThirtyDays: false,
      },
    });
  };

  const handleRemoveServiceItems = () => {
    const newAppliedFilters = {
      ...appliedFilters,
      serviceItems: [],
    };
    updateAppliedFilters(newAppliedFilters as MetricFiltersForm);
    form.setValue(metricFilterFields.serviceItems(), []);
  };

  const handleRemoveDateRange = () => {
    setSelectedDates(null);
    const newFilters = {
      ...EMPTY_FILTERS,
      serviceItems: appliedFilters?.serviceItems || [],
    };
    updateAppliedFilters(newFilters);
    form.reset(newFilters);
  };

  const handleCloseDrawer = () => {
    if (appliedFilters) {
      form.reset(appliedFilters);
    } else {
      form.reset(EMPTY_FILTERS);
    }
    setFiltersDrawerOpen(false);
  };

  const handleOpenCsatRatingFilterMenu = (
    event: React.MouseEvent<HTMLButtonElement>,
  ) => {
    setAnchorEl(event.currentTarget);
  };

  const handleCloseCsatRatingFilterMenu = () => {
    setAnchorEl(null);
  };

  const handleSelectRating = useCallback(
    (formNameValue: keyof RatingForm) => {
      const currentValue = ratingForm.getValues()[formNameValue];
      ratingForm.setValue(formNameValue, !currentValue);
    },
    [ratingForm],
  );

  const ratingItems = useMemo(() => {
    const values = ratingForm.getValues();
    return Object.keys(values).map(key => {
      return {
        name: key,
        label: t('rating_n', { rating: key }),
        onSelect: () => handleSelectRating(key as keyof RatingForm),
      };
    });
  }, [t, ratingForm, handleSelectRating]);

  const handleApplyRatings = () => {
    const selectedRatings = Object.keys(ratingForm.getValues()).filter(
      key => ratingForm.getValues()[key as keyof RatingForm],
    );
    setAppliedRatings(selectedRatings);
    handleCloseCsatRatingFilterMenu();
  };

  const handleClearRatings = () => {
    ratingForm.reset();
    setAppliedRatings([]);
    handleCloseCsatRatingFilterMenu();
  };

  const getRatingDescription = () => {
    if (averageCsatRating > 4.5) {
      return t('csat_5_rating');
    }
    if (averageCsatRating > 3.5) {
      return t('csat_4_rating');
    }
    if (averageCsatRating > 2.5) {
      return t('csat_3_rating');
    }
    if (averageCsatRating > 1.5) {
      return t('csat_2_rating');
    }
    return t('csat_1_rating');
  };

  const handleOpenDownloadReportDrawer = () => {
    // Before opening the drawer we set the date options and the service items of the report form to
    // the values currently selected in the global filter forms
    const globalFilterValues = form.getValues();
    const reportFilterValues = downloadReportForm.getValues();

    const serviceItems = globalFilterValues.serviceItems || [];
    const includeServiceItems = serviceItems.length > 0;
    const dateOptions = globalFilterValues.dateOptions || {};
    const startDate = globalFilterValues.startDate || null;
    const endDate = globalFilterValues.endDate || null;

    downloadReportForm.reset({
      ...reportFilterValues,
      includeServiceItems,
      serviceItems: serviceItems.map(item => ({
        label: item.name,
        value: String(item.id),
      })),
      dateOptions,
      startDate,
      endDate,
    });

    setDownloadCsatReportDrawerOpen(true);
  };

  const handleCloseDownloadReportDrawer = () => {
    setDownloadCsatReportDrawerOpen(false);
  };

  const handleResetDownloadReportForm = () => {
    const values = downloadReportForm.getValues();
    downloadReportForm.reset({
      email: values.email,
      ...DEFAULT_REPORT_FORM_VALUES,
    });
  };

  const isTasksSectionLoading = isLoadingModuleConfiguration || isTasksLoading;
  const isCsatSectionLoading = isLoadingModuleConfiguration || isCsatLoading;
  const isCsatTableLoading = isLoadingModuleConfiguration || isLoadingTableData;

  const showEmptyTasksResults =
    !isTasksError && !isTasksSectionLoading && requestsCount === 0;
  const showEmptyCsatResults =
    !isCsatError &&
    !isCsatSectionLoading &&
    totalCsatResponses <= MINIMUM_RESPONSES_TO_SHOW; // 3 is the minimum number of responses to show the chart!
  const csatDisabled =
    !isLoadingModuleConfiguration &&
    !moduleConfiguration?.csatEnabled &&
    totalCsatResponses === 0;
  const showDownloadCsatReportButton =
    canDownloadCsatReport &&
    !isCsatError &&
    !isCsatSectionLoading &&
    !showEmptyCsatResults;

  const showMainContent = isLoadingModuleConfiguration || moduleActivated;
  const showActivateModuleCard =
    !moduleActivated && !isLoadingModuleConfiguration;

  return (
    <HuGoThemeProvider>
      <Helmet>
        <title>{formatTitle(t('metrics_title'))}</title>
      </Helmet>
      <FormProvider {...form}>
        <Stack
          sx={{
            minHeight: 1,
            width: 1,
            backgroundColor: ({ palette }) =>
              palette?.new.background.layout.default,
          }}
        >
          <Container
            maxWidth="lg"
            sx={{
              alignItems: 'flex-start',
              display: 'flex',
              flexDirection: 'column',
              gap: showActivateModuleCard ? 3 : 4,
              pt: 8,
              pb: 4,
              px: 2,
              marginInline: 'auto',
              width: 1,
              height: '100%',
            }}
            disableGutters
          >
            <HuTitle
              title={t('metrics_title')}
              variant="XL"
            />
            {showActivateModuleCard && <ActivateModuleCard />}
            {showMainContent && (
              <>
                <MetricFiltersDrawer
                  open={filtersDrawerOpen}
                  onClose={handleCloseDrawer}
                  onConfirm={handleConfirmFilters}
                  onReset={handleCleanFilters}
                />
                <MetricFiltersControls
                  loading={isLoadingModuleConfiguration}
                  selectedDates={selectedDates}
                  serviceItems={appliedFilters?.serviceItems || []}
                  onRemoveServiceItems={handleRemoveServiceItems}
                  onRemoveDateRange={handleRemoveDateRange}
                  onOpenFilters={() => setFiltersDrawerOpen(true)}
                />
                <HuCardContainer fullWidth>
                  <Stack sx={{ gap: 2 }}>
                    <HuTitle
                      title={t('metrics_general_title')}
                      description={t('metrics_general_description')}
                      variant="M"
                    />
                    {isTasksError && (
                      <StateCard
                        title={t('error_cant_show_results')}
                        description={t('error_refresh_page_or_try_later')}
                        variant="error"
                        primaryAction={{
                          label: t('try_again'),
                          onClick: () => refetchTaskData(),
                        }}
                        slotProps={{
                          card: {
                            sx: {
                              padding: 2,
                              border: 'none',
                            },
                          },
                        }}
                      />
                    )}
                    {showEmptyTasksResults && (
                      <StateCard
                        variant="primary"
                        title={t('no_results_for_selection_title')}
                        description={t(
                          'no_results_for_selection_service_chart',
                        )}
                        slotProps={{
                          card: {
                            sx: {
                              border: 'none',
                            },
                          },
                        }}
                      />
                    )}
                    {!isTasksError && !showEmptyTasksResults && (
                      <Stack
                        sx={{
                          width: '100%',
                          alignItems: 'stretch',
                          gap: 2,
                          flexDirection: {
                            xs: 'column',
                            md: 'row',
                          },
                        }}
                      >
                        <Stack
                          sx={{
                            width: { xs: '100%', md: '255px' },
                            p: 2,
                            borderRadius: 2,
                            backgroundColor: theme =>
                              theme.palette.new.background.layout.default,
                            alignItems: 'start',
                            justifyContent: 'center',
                          }}
                        >
                          <InfoCard
                            title={requestsCount?.toLocaleString()}
                            copetin={t('requests_count')}
                            description={t('active_service_items_count', {
                              formattedCount:
                                activeServiceItemsCount?.toLocaleString(),
                            })}
                            loading={isTasksSectionLoading}
                          />
                        </Stack>
                        <Stack
                          sx={{
                            p: 2,
                            borderRadius: 2,
                            flex: 1, // takes the remaining width
                            maxWidth: {
                              xs: '100%',
                              md: 'calc(100% - 255px - 16px)',
                            },
                            height: '300px', // imposes the height
                            backgroundColor: theme =>
                              theme.palette.new.background.layout.default,
                          }}
                        >
                          <Typography
                            variant="globalS"
                            sx={{
                              color: ({ palette }) =>
                                palette.new.text.neutral.lighter,
                            }}
                          >
                            {t('metrics_general_chart_title')}
                          </Typography>
                          <ServiceItemsStateChart
                            labels={tasksChartData[0] || []}
                            data={tasksChartData[1] || []}
                            loading={isTasksSectionLoading}
                          />
                        </Stack>
                      </Stack>
                    )}
                  </Stack>
                </HuCardContainer>
                {!csatDisabled && (
                  <HuCardContainer fullWidth>
                    <Stack sx={{ gap: 2 }}>
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          alignItems: 'center',
                          gap: 2,
                          justifyContent: 'space-between',
                        }}
                      >
                        <HuTitle
                          title={t('csat_title')}
                          description={t('csat_description')}
                          variant="M"
                        />
                        {showDownloadCsatReportButton && (
                          <>
                            <Button
                              variant="secondary"
                              size="small"
                              sx={{ fontSize: '14px' }}
                              startIcon={<IconDownload size={16} />}
                              onClick={handleOpenDownloadReportDrawer}
                            >
                              {t('general:download')}
                            </Button>
                            <FormProvider {...downloadReportForm}>
                              <DownloadCsatReportDrawer
                                open={downloadCsatReportDrawerOpen}
                                onClose={handleCloseDownloadReportDrawer}
                                onReset={handleResetDownloadReportForm}
                              />
                            </FormProvider>
                          </>
                        )}
                      </Stack>
                      {isCsatError && (
                        <StateCard
                          title={t('error_cant_show_results')}
                          description={t('error_refresh_page_or_try_later')}
                          variant="error"
                          slotProps={{
                            card: {
                              sx: {
                                border: 'none',
                              },
                            },
                          }}
                          primaryAction={{
                            label: t('try_again'),
                            onClick: () => refetchCsatData(),
                            loading: isCsatLoading || isCsatRefetching,
                          }}
                        />
                      )}
                      {showEmptyCsatResults && (
                        <Stack sx={{ py: 3 }}>
                          <StateCard
                            title={t('no_results_for_selection_title')}
                            description={t(
                              'no_results_for_selection_description',
                            )}
                            variant="primary"
                            slotProps={{
                              card: {
                                sx: {
                                  border: 'none',
                                },
                              },
                            }}
                          />
                        </Stack>
                      )}
                      {!isCsatError && !showEmptyCsatResults && (
                        <Stack
                          sx={{
                            width: '100%',
                            alignItems: 'stretch',
                            gap: 2,
                            flexDirection: {
                              xs: 'column',
                              md: 'row',
                            },
                          }}
                        >
                          <Stack
                            sx={{
                              width: { xs: '100%', md: '255px' },
                              p: 2,
                              borderRadius: 2,
                              backgroundColor: ({ palette }) =>
                                palette.new.background.layout.default,
                              alignItems: 'start',
                              justifyContent: 'center',
                            }}
                          >
                            <InfoCard
                              loading={isCsatSectionLoading}
                              title={averageCsatRating
                                .toFixed(2)
                                .toLocaleString()}
                              subtitle={getRatingDescription()}
                              copetin={t('average_rating')}
                              description={t('responses_count', {
                                formattedCount:
                                  totalCsatResponses.toLocaleString(),
                              })}
                            />
                          </Stack>
                          <Stack
                            sx={{
                              p: 2,
                              borderRadius: 2,
                              flex: 1, // takes the remaining width
                              maxWidth: {
                                xs: '100%',
                                md: 'calc(100% - 255px - 16px)',
                              },
                              height: '300px', // imposes the height
                              backgroundColor: ({ palette }) =>
                                palette.new.background.layout.default,
                            }}
                          >
                            <Typography
                              variant="globalS"
                              sx={{
                                color: ({ palette }) =>
                                  palette.new.text.neutral.lighter,
                              }}
                            >
                              {t('csat_chart_title')}
                            </Typography>
                            <CsatChart
                              data={csatChartData[1] || []}
                              loading={isCsatSectionLoading}
                            />
                          </Stack>
                        </Stack>
                      )}
                      {!showEmptyCsatResults && (
                        <Stack
                          sx={{
                            gap: 2,
                            px: 2,
                            py: 3,
                            borderRadius: 2,
                            backgroundColor: ({ palette }) =>
                              palette.new.background.layout.default,
                          }}
                        >
                          {!isErrorTableData && (
                            <Stack
                              sx={{
                                flexDirection: 'row',
                                alignItems: 'center',
                                justifyContent: 'space-between',
                              }}
                            >
                              <Typography
                                variant="globalS"
                                sx={{
                                  color: ({ palette }) =>
                                    palette.new.text.neutral.lighter,
                                }}
                              >
                                {t('rating_motive')}
                              </Typography>
                              <Stack
                                sx={{
                                  flexDirection: 'row',
                                  alignItems: 'center',
                                  gap: 1,
                                }}
                              >
                                <FormProvider {...ratingForm}>
                                  <BadgeCountButton
                                    count={appliedRatingsCount}
                                    buttonText={t('general:filter')}
                                    buttonProps={{
                                      onClick: handleOpenCsatRatingFilterMenu,
                                      variant: 'secondary',
                                      size: 'small',
                                      sx: { fontSize: '14px' },
                                      endIcon: (
                                        <IconChevronDown
                                          size={16}
                                          color={
                                            theme.palette.new.text.neutral.brand
                                          }
                                          style={{
                                            transform: open
                                              ? 'rotate(180deg)'
                                              : 'rotate(0deg)',
                                            transition:
                                              'transform 0.3s ease-in-out',
                                          }}
                                        />
                                      ),
                                      startIcon: (
                                        <IconFilter
                                          size={16}
                                          color={
                                            theme.palette.new.text.neutral.brand
                                          }
                                        />
                                      ),
                                    }}
                                  />
                                  <HuMenu
                                    open={open}
                                    anchorEl={anchorEl}
                                    onClose={handleCloseCsatRatingFilterMenu}
                                    position="right"
                                    fixedDimensions={false}
                                    sx={{ width: '360px' }}
                                    header={
                                      <Stack
                                        sx={{
                                          p: 2,
                                          boxSizing: 'border-box',
                                        }}
                                      >
                                        <Typography
                                          variant="globalS"
                                          fontWeight="fontWeightSemiBold"
                                          noWrap
                                        >
                                          {t('filter_by_rating')}
                                        </Typography>
                                      </Stack>
                                    }
                                    footer={
                                      <Stack
                                        sx={{
                                          flexDirection: 'row',
                                          alignItems: 'center',
                                          gap: 1,
                                          width: 1,
                                        }}
                                      >
                                        <Button
                                          variant="tertiary"
                                          fullWidth
                                          onClick={handleClearRatings}
                                        >
                                          {t('reset')}
                                        </Button>
                                        <Button
                                          variant="primary"
                                          fullWidth
                                          onClick={handleApplyRatings}
                                        >
                                          {t('general:apply')}
                                        </Button>
                                      </Stack>
                                    }
                                  >
                                    {ratingItems.map(item => (
                                      <HuMenuItem
                                        key={item.name}
                                        sx={{ overflow: 'hidden' }}
                                        onClick={e => {
                                          e.stopPropagation();
                                          e.preventDefault();
                                          item.onSelect();
                                        }}
                                      >
                                        <HuFormCheckbox
                                          name={item.name}
                                          checkBoxProps={{
                                            label: item.label,
                                            sx: {
                                              overflow: 'hidden',
                                              '& .MuiFormControlLabel-label': {
                                                overflow: 'hidden',
                                                textOverflow: 'ellipsis',
                                                whiteSpace: 'nowrap',
                                              },
                                            },
                                          }}
                                        />
                                      </HuMenuItem>
                                    ))}
                                  </HuMenu>
                                </FormProvider>
                              </Stack>
                            </Stack>
                          )}
                          {isErrorTableData && (
                            <StateCard
                              variant="error"
                              title={t('error_cant_show_results')}
                              description={t('error_refresh_page_or_try_later')}
                              primaryAction={{
                                label: t('try_again'),
                                onClick: () => refetchTableData(),
                                loading:
                                  isLoadingTableData || isRefetchingTableData,
                              }}
                              slotProps={{
                                card: {
                                  sx: {
                                    border: 'none',
                                  },
                                },
                              }}
                            />
                          )}
                          {!isErrorTableData && (
                            <CsatTable
                              ratings={csatTableData}
                              loading={isCsatTableLoading}
                              fetchNextPage={fetchNextPage}
                              hasNextPage={hasNextPage}
                              isFetchingNextPage={isFetchingNextPage}
                            />
                          )}
                        </Stack>
                      )}
                    </Stack>
                  </HuCardContainer>
                )}
              </>
            )}
          </Container>
        </Stack>
      </FormProvider>
    </HuGoThemeProvider>
  );
};

export default Metrics;
