import { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import { type DefaultValues, FormProvider, useForm } from 'react-hook-form';
import { type UseQueryResult } from 'react-query';

import { fromPairs, mapValues } from 'lodash-es';
import { IconFilter } from '@material-hu/icons/tabler';
import Badge from '@material-hu/mui/Badge';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';

import Button from '@material-hu/components/design-system/Buttons/Button';

import { logEvent } from 'src/config/amplitude';
import { EventName } from 'src/types/amplitude';
import {
  type Incidence,
  type ReportFilterFields,
  type SegmentationGroup,
  type UserTrackingStatus,
} from 'src/types/timeTracking';
import { countAppliedFilters } from 'src/utils/filters';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { mapTrueKeys } from 'src/utils/timeTracking';

import { type TwoFieldGroup } from 'src/components/AdvancedFilter/types';
import { type BaseUser } from 'src/components/dashboard/filterDrawer/FormUserAutocomplete';
import { useFiltersDrawer } from 'src/components/dashboard/filterDrawer/useFiltersDrawer';

import DropdownFilter from '../pages/dashboard/timeTracking/components/DropdownFilter';
import { LOG_DELAY_MS } from '../pages/dashboard/timeTracking/constants';
import {
  EXTENDED_INCIDENCES_FILTERS,
  getInitialFilterValues,
  USER_STATUSES,
} from '../pages/dashboard/timeTracking/PeriodCollaborators/components/ReportFilters/constants';

type Props = {
  segmentationGroups: SegmentationGroup[];
  isLoadingSegmentations: boolean;
  regions?: TwoFieldGroup[];
  isLoadingRegions?: boolean;
  enableSites?: boolean;
  enableQuickFilters?: boolean;
  showIncludeDeactivated?: boolean;
  usersQuery: (search: string) => UseQueryResult<BaseUser[]>;
  initialValues?: ReportFilterFields;
  onValuesChange?: (v: ReportFilterFields) => void;
};

export type ReportFilter = {
  component: ReactNode;
  values: ReportFilterFields;
  appliedFilters: boolean;
};

type IncidenceFilter = Incidence | 'PERMIT_DAY';

const DROPDOWN_SX = { '.MuiButtonBase-root': { height: '100%' } };
const EMPTY_ARRAY: TwoFieldGroup[] = [];

const useReportFilters = (props: Props): ReportFilter => {
  const {
    isLoadingSegmentations,
    segmentationGroups,
    regions,
    isLoadingRegions = false,
    enableSites = true,
    enableQuickFilters = true,
    showIncludeDeactivated = false,
    usersQuery,
    initialValues,
    onValuesChange,
  } = props;

  const { t } = useLokaliseTranslation(['time_tracker', 'general']);
  const [isOpen, setIsOpen] = useState(false);
  const [selectedIncidences, setSelectedIncidences] = useState<
    IncidenceFilter[]
  >([]);
  const [selectedStatuses, setSelectedStatuses] = useState<
    UserTrackingStatus[]
  >([]);
  const timerRef = useRef<NodeJS.Timeout | null>(null);

  const safeRegions = regions ?? EMPTY_ARRAY;

  const formInitialValues = useMemo<ReportFilterFields>(() => {
    const base =
      initialValues ??
      getInitialFilterValues(
        segmentationGroups,
        enableSites ? safeRegions : EMPTY_ARRAY,
      );

    const sites = enableSites ? base : { ...base, siteIds: {} };

    if (!enableQuickFilters) {
      return {
        ...sites,
        incidencesItems: {},
        statusItems: {},
        hasHoliday: false,
        hasTimeOff: false,
        includeDeactivated: sites.includeDeactivated ?? false,
      };
    }
    return sites;
  }, [
    initialValues,
    segmentationGroups,
    enableSites,
    enableQuickFilters,
    safeRegions,
  ]);

  const [finalValues, setFinalValues] =
    useState<ReportFilterFields>(formInitialValues);

  const form = useForm<ReportFilterFields>({
    defaultValues: formInitialValues as DefaultValues<ReportFilterFields>,
  });

  const syncOut = (vals: ReportFilterFields) => {
    setFinalValues(vals);
    onValuesChange?.(vals);
  };

  const handleApply = (formValues: ReportFilterFields) => {
    form.reset(formValues);
    const next: ReportFilterFields = {
      ...formValues,
      ...(!enableSites && { siteIds: {} }),
      ...(enableQuickFilters
        ? {
            incidencesItems: fromPairs(selectedIncidences.map(o => [o, true])),
            statusItems: fromPairs(selectedStatuses.map(o => [o, true])),
          }
        : {
            incidencesItems: {},
            statusItems: {},
            hasHoliday: false,
            hasTimeOff: false,
          }),
    };
    syncOut(next);
    setIsOpen(false);
  };

  const clearFormFilters = () => {
    const currentValues = form.getValues();
    const resetValues: ReportFilterFields = {
      ...formInitialValues,
      segmentationItems: mapValues(
        currentValues.segmentationItems,
        () => false,
      ),
      siteIds: enableSites ? mapValues(currentValues.siteIds, () => false) : {},
      ...(enableQuickFilters
        ? {
            incidencesItems: fromPairs(selectedIncidences.map(o => [o, true])),
            statusItems: fromPairs(selectedStatuses.map(o => [o, true])),
            hasHoliday: currentValues.hasHoliday,
            hasTimeOff: currentValues.hasTimeOff,
          }
        : {
            incidencesItems: {},
            statusItems: {},
            hasHoliday: false,
            hasTimeOff: false,
          }),
    };
    form.reset(resetValues);
    syncOut(resetValues);
  };

  const clearAllFilters = () => {
    const blank = getInitialFilterValues(
      segmentationGroups,
      enableSites ? safeRegions : EMPTY_ARRAY,
    );

    const cleared: ReportFilterFields = {
      ...blank,
      segmentationItems: mapValues(blank.segmentationItems, () => false),
      ...(enableSites
        ? { siteIds: mapValues(blank.siteIds, () => false) }
        : { siteIds: {} }),
      users: [],
      incidencesItems: {},
      statusItems: {},
      hasHoliday: false,
      hasTimeOff: false,
      includeDeactivated: false,
    };

    form.reset(cleared);
    syncOut(cleared);
    setSelectedStatuses([]);
    setSelectedIncidences([]);

    setIsOpen(false);
  };

  const clearDraftValues = () => {
    form.reset(finalValues);
    setIsOpen(false);
  };

  const logQuickFiltersChange = (
    incidences: IncidenceFilter[],
    statuses: UserTrackingStatus[],
  ) => {
    if (!enableQuickFilters) return;
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      logEvent(
        EventName['TIME_TRACKING_CONTROL_MODULE_INCIDENTS&STATUS_FILTERED'],
        {
          status: statuses.join(', '),
          incidents: incidences.join(', '),
        },
      );
    }, LOG_DELAY_MS);
  };

  const handleIncidenceChange = (appliedIncidences: IncidenceFilter[]) => {
    if (!enableQuickFilters) return;
    setSelectedIncidences(appliedIncidences);
    const incidences = appliedIncidences.filter(i => i !== 'PERMIT_DAY');
    const isPermitDay = appliedIncidences.includes('PERMIT_DAY');

    const next: ReportFilterFields = {
      ...finalValues,
      incidencesItems: fromPairs(incidences.map(o => [o, true])),
      hasHoliday: isPermitDay,
      hasTimeOff: isPermitDay,
    };
    syncOut(next);
    logQuickFiltersChange(appliedIncidences, selectedStatuses);
  };

  const handleStatusChange = (appliedStatuses: UserTrackingStatus[]) => {
    if (!enableQuickFilters) return;
    setSelectedStatuses(appliedStatuses);

    const next: ReportFilterFields = {
      ...finalValues,
      statusItems: fromPairs(appliedStatuses.map(o => [o, true])),
    };
    syncOut(next);
    logQuickFiltersChange(selectedIncidences, appliedStatuses);
  };

  const { showFiltersDrawer, filtersDrawer } = useFiltersDrawer({
    disabledClearButton:
      countAppliedFilters([
        Object.values(finalValues.segmentationItems).some(Boolean),
        ...(enableSites
          ? [Object.values(finalValues.siteIds).some(Boolean)]
          : []),
        finalValues.users.length > 0,
        ...(showIncludeDeactivated ? [finalValues.includeDeactivated] : []),
      ]) === 0,
    segmentationGroups,
    regions: safeRegions,
    isLoadingSegmentations,
    isLoadingRegions,
    handleApply: () => handleApply(form.getValues()),
    clearFilters: clearFormFilters,
    clearDraftValues,
    hideSites: !enableSites,
    showIncludeDeactivated,
    usersQuery,
  });

  const appliedFiltersBase = [
    Object.values(finalValues.segmentationItems).some(Boolean),
    ...(enableSites ? [Object.values(finalValues.siteIds).some(Boolean)] : []),
    finalValues.users.length > 0,
    ...(showIncludeDeactivated ? [finalValues.includeDeactivated] : []),
  ];
  const appliedFiltersNumber = countAppliedFilters(appliedFiltersBase);
  const appliedQuickFilters = enableQuickFilters
    ? Object.values(finalValues.statusItems).some(Boolean) ||
      Object.values(finalValues.incidencesItems).some(Boolean)
    : false;

  useEffect(() => {
    form.reset(formInitialValues);
    syncOut(formInitialValues);
  }, [formInitialValues]);

  useEffect(() => {
    if (!enableQuickFilters) return;
    const incidences = mapTrueKeys<IncidenceFilter>(
      finalValues.incidencesItems,
    );
    setSelectedIncidences(
      finalValues.hasHoliday || finalValues.hasTimeOff
        ? [...incidences, 'PERMIT_DAY']
        : incidences,
    );
    setSelectedStatuses(
      mapTrueKeys<UserTrackingStatus>(finalValues.statusItems),
    );
  }, [finalValues, enableQuickFilters]);

  useEffect(() => {
    if (!isOpen) form.reset(finalValues);
  }, [isOpen]);

  const component = (
    <FormProvider {...form}>
      {filtersDrawer}
      <Stack sx={{ flexDirection: 'row', gap: 1 }}>
        {enableQuickFilters && (
          <>
            <DropdownFilter
              applyFilters={handleStatusChange}
              options={USER_STATUSES}
              dropdownLabel={t('STATUSES')}
              state={selectedStatuses}
              sx={DROPDOWN_SX}
            />
            <DropdownFilter
              applyFilters={handleIncidenceChange}
              options={EXTENDED_INCIDENCES_FILTERS}
              dropdownLabel={t('INCIDENCES')}
              state={selectedIncidences}
              sx={DROPDOWN_SX}
            />
          </>
        )}

        <IconButton
          aria-label={t('general:filter')}
          variant="secondary"
          onClick={() => {
            setIsOpen(true);
            showFiltersDrawer({});
          }}
        >
          <IconFilter />
          {appliedFiltersNumber > 0 && (
            <Badge
              color="primary"
              badgeContent={appliedFiltersNumber}
              sx={{ position: 'absolute', top: 0, right: 0 }}
            />
          )}
        </IconButton>

        {(appliedFiltersNumber > 0 ||
          (enableQuickFilters && appliedQuickFilters)) && (
          <Button
            variant="text"
            onClick={clearAllFilters}
          >
            {t('REMOVE_FILTERS')}
          </Button>
        )}
      </Stack>
    </FormProvider>
  );

  return {
    component,
    values: finalValues,
    appliedFilters: appliedFiltersNumber > 0,
  };
};

export default useReportFilters;
