import { useCallback, useEffect, useRef, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { FormProvider, useForm } from 'react-hook-form';
import { useQuery } from 'react-query';

import {
  /* COACHMARK DISABLED: addDays, format */
  eachDayOfInterval,
} from 'date-fns';
import { useModal } from '@material-hu/hooks/useModal';
import Stack from '@material-hu/mui/Stack';
import { type Theme, useTheme } from '@material-hu/mui/styles';

import { WeekMonthPeriod } from '@material-hu/components/composed-components/WeekMonthSelector/types';
import Dialog from '@material-hu/components/design-system/Dialog';
import TaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import Title from '@material-hu/components/design-system/Title';

import { logEvent } from 'src/config/amplitude';
import { useAuth } from 'src/contexts/JWTContext';
import { useLayoutContext } from 'src/contexts/LayoutContext';
import { useDebounce } from 'src/hooks/useDebounce';
import useFormatDate from 'src/hooks/useFormatDate';
import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useReportFilters from 'src/hooks/useReportFilters';
import { getSegmentationGroups } from 'src/services/segmentations';
import { getUsers } from 'src/services/shifts';
import { EventName, ShiftManagementMenuSource } from 'src/types/amplitude';
import { type SegmentationGroup } from 'src/types/timeTracking';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { isAdmin } from 'src/utils/permissions';

import { selectedItemsToString } from 'src/components/AdvancedFilter/utils';
import { parseGroup } from 'src/components/dashboard/filterDrawer/utils';

import { feedKeys } from '../feed/queries';

import { useAssignShiftDrawer } from './components/CustomShiftsDrawer/useAssignShiftDrawer';
import AssignTemplateDrawerController from './components/AssignTemplateDrawer/AssignTemplateDrawerController';
import { useAssignTemplateDrawer } from './hooks/useAssignTemplateDrawer';
import { useDuplicateShiftsDrawer } from './components/DuplicateShiftsDrawer/useDuplicateShiftsDrawer';
import MonthlyDragModal from './components/MonthlyDragModal';
/* COACHMARK DISABLED - kept for future reference
import ShiftsCoachmark, {
  ShiftsCoachmarkProvider,
  useShiftsCoachmark,
  generateCoachmarkMockData,
  COACHMARK_MOCK_SHIFT_ID,
  COACHMARK_MOCK_USER_ID,
} from './components/ShiftsCoachmark';
*/
import ShiftsTable from './components/ShiftsTable';
import { TABLE_FILTERS_STICKY_SX } from './components/ShiftsTable/constants';
import TableConfigurations from './components/TableConfigurations';
import {
  ShiftsSelectionProvider,
  useShiftsSelectionActions,
} from './contexts/ShiftsSelectionContext';
import { CUSTOM_SHIFT_INITIAL_VALUES, type ShiftFormData } from './form';
import { useGetShiftsCalendar } from './hooks/queryHooks';
import { useShiftBulkDelete } from './hooks/useShiftBulkDelete';
import { useShiftCopyPaste } from './hooks/useShiftCopyPaste';
import { useShiftDragDrop } from './hooks/useShiftDragDrop';
import { useShiftsKeyboardShortcuts } from './hooks/useShiftsKeyboardShortcuts';
import { useSyncScroll } from './hooks/useSyncScroll';
import { shiftsKeys } from './queries';
import { getCellShifts } from './utils';
import { buildShiftManagementFilteredPayload } from './utils/trackFilterPayload';

// Component wrapped in ContextProvider
const ShiftsContent = () => {
  const [search, setSearch] = useState('');
  const [selectedSite, setSelectedSite] = useState<null | {
    name: string;
    id: number;
  }>(null);

  const {
    startDate,
    endDate,
    clearAllSelections,
    closeOpenOverlays,
    isAdvancedMode,
    selectedDates,
    selectedCells,
    selectedShifts,
    // setSelectedShifts,
    // setSelectedCells,
    clearSelectedCells,
    toggleSelectAll,
    allRowsSelected,
    excludeCells,
    viewMode,
  } = useShiftsSelectionActions();

  // const { palette } = useTheme();
  const isMonthlyView = viewMode === WeekMonthPeriod.MONTHLY;

  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation([
    'shifts',
    'time_tracker',
    'time_tracking_common',
  ]);
  const { formatDate } = useFormatDate();
  const showGeneralError = useGeneralError();
  const { taskFocus, setTaskFocus } = useLayoutContext();
  const { permissions } = useAuth();

  const days = eachDayOfInterval({ start: startDate, end: endDate }).map(d => ({
    key: formatDate(d, 'yyyy-MM-dd'),
    label: formatDate(d, 'EEE, dd'),
  }));

  const SCROLL_AMOUNT = 5 * (isMonthlyView ? 67 : 120);

  const { data: segmentationGroups = [], isLoading: isLoadingSegmentations } =
    useQuery(feedKeys.segmentate.groups(), () => getSegmentationGroups(), {
      select: response => parseGroup(response.data) as SegmentationGroup[],
      onError: error => {
        showGeneralError(
          error,
          t('time_tracker:error_loading_segmentation_groups'),
        );
      },
    });

  const usersQuery = (searchQuery: string) =>
    useQuery(
      shiftsKeys.getUsers({ search: searchQuery, siteId: selectedSite?.id }),
      () =>
        getUsers({
          page: 1,
          limit: 30,
          search: searchQuery,
          siteId: selectedSite?.id,
        }),
      {
        select: data => data.data.items,
      },
    );

  const logFilteredEvent = useCallback(
    (
      siteFilters: boolean,
      segmentationItems: Record<string, boolean>,
      selectedCollaboratorsCount: number,
    ) => {
      logEvent(EventName.SHIFT_MANAGEMENT_FILTERED, {
        ...buildShiftManagementFilteredPayload(
          siteFilters,
          segmentationItems,
          segmentationGroups,
          selectedCollaboratorsCount,
        ),
      });
    },
    [segmentationGroups],
  );

  const drawerFilters = useReportFilters({
    segmentationGroups,
    isLoadingSegmentations,
    isLoadingRegions: false,
    enableSites: false,
    enableQuickFilters: false,
    usersQuery: usersQuery,
    onValuesChange: vals => {
      clearAllSelections({ keepCopiedCells: true });
      logFilteredEvent(
        !!selectedSite,
        vals.segmentationItems,
        vals.users.length,
      );
    },
  });

  const onSiteFilterChange = useCallback(
    (site: { id: number; name: string } | null) => {
      logFilteredEvent(
        !!site,
        drawerFilters.values.segmentationItems,
        drawerFilters.values.users.length,
      );
    },
    [
      logFilteredEvent,
      drawerFilters.values.segmentationItems,
      drawerFilters.values.users.length,
    ],
  );

  const { debouncedValue: debouncedValues, isDebouncing } = useDebounce({
    startDate: formatDate(startDate, 'yyyy-MM-dd'),
    endDate: formatDate(endDate, 'yyyy-MM-dd'),
    search,
    userIds: drawerFilters.values.users.map(u => u.id).join(','),
    siteId: selectedSite?.id || null,
    segmentationItemIds: selectedItemsToString(
      drawerFilters.values.segmentationItems,
    ),
  });

  /* COACHMARK DISABLED - kept for future reference
  // Coachmark state - show mock data when coachmark is active
  const { hasCompletedCoachmark, registerOnStepChange } = useShiftsCoachmark();
  const isCoachmarkActive = !hasCompletedCoachmark;
  */

  const {
    registers,
    currentUserCount,
    isLoadingCollaborators,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    totalUserCount,
  } = useGetShiftsCalendar(debouncedValues);

  /* COACHMARK DISABLED - kept for future reference
  // Generate mock data for coachmark or use real data
  const mockRegisters = generateCoachmarkMockData(
    debouncedValues.startDate,
    debouncedValues.endDate,
  );

  const registers = isCoachmarkActive ? mockRegisters : realRegisters;
  const currentUserCount = isCoachmarkActive ? 1 : realCurrentUserCount;
  const totalUserCount = isCoachmarkActive ? 1 : realTotalUserCount;

  // Register callback to handle coachmark step changes
  useEffect(() => {
    if (hasCompletedCoachmark) return;

    const handleStepChange = (step: number) => {
      if (step === 1) {
        // Step 1: Select the mock shift
        const mockShiftSelection = new Map([
          [
            COACHMARK_MOCK_SHIFT_ID,
            {
              shiftId: COACHMARK_MOCK_SHIFT_ID,
              userId: COACHMARK_MOCK_USER_ID,
              date: debouncedValues.startDate,
            },
          ],
        ]);
        setSelectedShifts(mockShiftSelection);
        setSelectedCells([]);
      } else if (step === 2) {
        // Step 2: Deselect shift, select empty cell on day 2
        const secondDayDate = format(
          addDays(new Date(debouncedValues.startDate), 2),
          'yyyy-MM-dd',
        );
        setSelectedShifts(new Map());
        setSelectedCells([
          { userId: COACHMARK_MOCK_USER_ID, date: secondDayDate },
        ]);
      } else if (step === 3) {
        // Step 3: Deselect cell (menu opens automatically via ActionButtons)
        setSelectedShifts(new Map());
        setSelectedCells([]);
      }
    };

    return registerOnStepChange(handleStepChange);
  }, [
    hasCompletedCoachmark,
    registerOnStepChange,
    debouncedValues.startDate,
    setSelectedShifts,
    setSelectedCells,
  ]);
  */

  const { executeCopy, executePaste } = useShiftCopyPaste({
    registers: registers || [],
    filters: debouncedValues,
    days,
  });

  const {
    handleDragStart,
    handleDragOver,
    handleDragLeave,
    handleDrop,
    handleDragEnd,
    dragOverCell,
    draggingShiftIds,
    optimisticMove,
    dragPreviewMap,
  } = useShiftDragDrop({ registers: registers || [] });

  // Sync scroll between the 2 separate tables: header and body
  const { firstRefCallback, secondRefCallback, scrollByAmount } =
    useSyncScroll();

  /*
    Double table workaround context:
    Having 2 separate tables is a workaround to ensure that the table header is sticky and it remains on the same
    flow / "scrolling scope" with the filters and search section.
    It's not ideal, but it allows users with small screens to not feel constraint by the reduced table dimensions,
    and to scroll the table directly from the page focus, without the need to hover over the table to scroll.
    
    Note about accessibility: its not good to have a table header and body separated,
    it will break screen readers navigation and make the table sort of a headache to navigate.
    We cannot use a single table with a sticky header, because:
      1. Header should be in the same "scrolling scope" as the filters and search section,
      2. The table header sticky position does not work without setting a max-height
      3. Also we may achieve the desired effect by removing the overflowX: auto from the table container,
      but then the table will not be scrollable horizontally, and the user will not be able to scroll the table
      to see the entire table on reduced screen sizes.

    Currently we are reviewing a better approach to achieve the same effect,
  */

  const form = useForm<ShiftFormData>({
    defaultValues: { ...CUSTOM_SHIFT_INITIAL_VALUES },
    mode: 'onSubmit',
  });

  const {
    assignmentErrorModal,
    runningAssignmentModal,
    AssignShiftDrawer,
    saveShiftInRepositoryModal,
    showAssignShiftDrawer,
    assignShiftMutation,
    showAssigningModal,
  } = useAssignShiftDrawer({
    form,
    debouncedValues,
    totalUserCount,
    onClearSelections: clearAllSelections,
  });
  const { showAssignTemplateDrawer, registerOpen } = useAssignTemplateDrawer();

  const {
    ConfirmDuplicateModal,
    ConfirmDiscardChangesModal,
    DuplicateConflictErrorModal,
    DuplicateShiftsDrawer,
    showDuplicateShiftsDrawer,
  } = useDuplicateShiftsDrawer({
    filters: debouncedValues,
    filteredUsersCount: currentUserCount,
  });
  const isLoading = isLoadingCollaborators || isDebouncing;

  const { executeBulkDelete, isDeletingShifts } = useShiftBulkDelete({
    filters: debouncedValues,
    onSuccess: () => {
      closeRemoveAllShiftsModal();
    },
  });

  const {
    modal: removeAllShiftsModal,
    showModal: showRemoveAllShiftsModal,
    closeModal: closeRemoveAllShiftsModal,
  } = useModal(
    Dialog,
    { fullWidth: true, maxWidth: 'sm' },
    {
      title: t('shifts:remove_modal.bulk_title'),
      textBody: t('shifts:remove_modal.bulk_description'),
      primaryButtonProps: {
        loading: isDeletingShifts,
        children: t('shifts:remove_shift_other'), // Plural form
        onClick: () => {
          executeBulkDelete();
        },
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        disabled: isDeletingShifts,
        onClick: () => {
          closeRemoveAllShiftsModal();
        },
      },
    },
  );

  const handleSelectAllKeyboard = useCallback(() => {
    toggleSelectAll(days, registers);
  }, [toggleSelectAll, registers, days]);

  const handleClearSelection = useCallback(
    () => clearAllSelections(),
    [clearAllSelections],
  );

  const isEverythingSelected = allRowsSelected && excludeCells.length === 0;

  // Keyboard shortcuts observer for copy/paste/delete commands
  useShiftsKeyboardShortcuts({
    onCopy: () => executeCopy(null, ShiftManagementMenuSource.KEYBOARD),
    onPaste: () => executePaste(undefined, ShiftManagementMenuSource.KEYBOARD),
    clearSelection: handleClearSelection,
    showRemoveShiftsConfirmationModal: showRemoveAllShiftsModal,
    isDeletingShifts: isDeletingShifts,
    areShiftsSelected:
      selectedShifts.size > 0 ||
      selectedCells.some(
        cell => getCellShifts(cell, registers || []).length > 0,
      ) ||
      selectedDates.size > 0,
    onSelectAll: handleSelectAllKeyboard,
    isEverythingSelected,
    // COACHMARK DISABLED - kept for future reference
    // disabled: isCoachmarkActive,
    clearSelectedCells,
    closeOpenOverlays,
  });

  const selectionActive =
    selectedDates.size > 0 || selectedCells.length > 0 || isAdvancedMode;

  // Track when shifts management screen is opened (only once)
  const hasTrackedOpen = useRef(false);
  useEffect(() => {
    if (
      !isLoadingCollaborators &&
      registers?.length !== undefined &&
      !hasTrackedOpen.current
    ) {
      hasTrackedOpen.current = true;
      logEvent(EventName.SHIFT_MANAGEMENT_OPENED, {
        colabs_number: registers?.length,
      });
    }
  }, [isLoadingCollaborators]);

  return (
    <HuGoThemeProvider>
      <AssignTemplateDrawerController registerOpen={registerOpen} />
      {assignmentErrorModal}
      {saveShiftInRepositoryModal}
      {removeAllShiftsModal}
      {runningAssignmentModal}
      {DuplicateShiftsDrawer}
      {ConfirmDuplicateModal}
      {ConfirmDiscardChangesModal}
      {DuplicateConflictErrorModal}
      {/* COACHMARK DISABLED - kept for future reference
      <ShiftsCoachmark />
      */}
      <MonthlyDragModal />
      <FormProvider {...form}>
        {AssignShiftDrawer}
        <Stack
          sx={{
            alignItems: 'center',
            backgroundColor: ({ palette }) =>
              palette.new.background.layout.default,
            minHeight: '100%',
          }}
        >
          <Helmet>
            <title>{formatTitle(t('work_shifts'))}</title>
          </Helmet>
          {taskFocus && (
            <TaskFocusHeader
              title={t('work_shifts')}
              onClose={() => setTaskFocus(false)}
              slotProps={{
                root: {
                  width: '100%',
                  position: 'sticky',
                  top: 0,
                  zIndex: 2,
                  borderBottom: ({ palette }: Theme) =>
                    `1px solid ${palette.new.border.neutral.default}`,
                },
              }}
            />
          )}
          <Stack
            sx={{
              ...(!taskFocus && { pt: 6, px: 3 }),
              width: '100%',
              height: '100%',
            }}
          >
            {!taskFocus && (
              <Title
                variant="L"
                title={t('work_shifts')}
                sx={{
                  mb: 4,
                }}
              />
            )}
            <Stack
              sx={{
                backgroundColor: ({ palette }: Theme) =>
                  palette.new.background.layout.tertiary,
                ...(!taskFocus && {
                  border: ({ palette }: Theme) =>
                    `1px solid ${palette.new.border.neutral.default}`,
                  borderRadius: ({ spacing }: Theme) => spacing(2),
                }),
                position: 'relative',
              }}
            >
              {/* COACHMARK DISABLED - kept for future reference
              Overlay to block interactions while coachmark is active
              {isCoachmarkActive && (
                <Stack
                  sx={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    zIndex: 10,
                    cursor: 'not-allowed',
                  }}
                />
              )}
              */}
              <Stack
                sx={{
                  backgroundColor: ({ palette }: Theme) =>
                    palette.new.background.layout.tertiary,
                  borderTopLeftRadius: ({ spacing }: Theme) => spacing(2),
                  borderTopRightRadius: ({ spacing }: Theme) => spacing(2),
                  gap: 2,
                  pb: 0,
                  ...TABLE_FILTERS_STICKY_SX(taskFocus),
                }}
              >
                <TableConfigurations
                  isLoading={isLoading}
                  setSelectedSite={setSelectedSite}
                  selectedSite={selectedSite}
                  onSiteFilterChange={onSiteFilterChange}
                  setSearch={setSearch}
                  search={search}
                  onAssignDayOff={assignShiftMutation}
                  showAssigningModal={showAssigningModal}
                  onRemoveAllShifts={showRemoveAllShiftsModal}
                  debouncedValues={debouncedValues}
                  registers={registers || []}
                  drawerFilters={drawerFilters}
                  showAssignShiftDrawer={showAssignShiftDrawer}
                  onCopy={() =>
                    executeCopy(null, ShiftManagementMenuSource.GLOBAL)
                  }
                  onPaste={targetCell =>
                    executePaste(targetCell, ShiftManagementMenuSource.GLOBAL)
                  }
                  userCount={`${currentUserCount}/${totalUserCount}`}
                  scrollRef={firstRefCallback}
                  days={days}
                  selectionActive={selectionActive}
                  showAssignTemplateDrawer={showAssignTemplateDrawer}
                  onOpenDuplicateShiftsDrawer={() =>
                    showDuplicateShiftsDrawer(debouncedValues)
                  }
                  toggleSelect={handleSelectAllKeyboard}
                  onScroll={dir => {
                    logEvent(
                      EventName.SHIFT_MANAGEMENT_MORE_DAYS_ARROW_CLICKED,
                      {
                        user_admin: isAdmin(permissions),
                        type: dir > 0 ? 'RIGHT' : 'LEFT',
                      },
                    );
                    scrollByAmount(dir * SCROLL_AMOUNT);
                  }}
                />
              </Stack>
              <ShiftsTable
                isLoading={isLoading}
                isFetchingNextPage={isFetchingNextPage}
                hasNextPage={hasNextPage || false}
                fetchNextPage={fetchNextPage}
                showAssignmentDrawer={showAssignShiftDrawer}
                totalRegisters={currentUserCount}
                registers={registers || []}
                onCopy={() =>
                  executeCopy(null, ShiftManagementMenuSource.SHIFT)
                }
                onPaste={targetCell =>
                  executePaste(targetCell, ShiftManagementMenuSource.SHIFT)
                }
                horizontalScrollRef={secondRefCallback}
                days={days}
                selectionActive={selectionActive}
                userCount={`${currentUserCount}/${totalUserCount}`}
                appliedFilters={
                  drawerFilters.appliedFilters || search.length > 0
                }
                // Drag & drop
                onDragStart={handleDragStart}
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onDrop={handleDrop}
                onDragEnd={handleDragEnd}
                dragOverCell={dragOverCell}
                draggingShiftIds={draggingShiftIds}
                optimisticMove={optimisticMove}
                dragPreviewMap={dragPreviewMap}
              />
            </Stack>
          </Stack>
        </Stack>
      </FormProvider>
    </HuGoThemeProvider>
  );
};

const Shifts = () => {
  return (
    /* COACHMARK DISABLED - kept for future reference
    <ShiftsCoachmarkProvider>
    */
    <ShiftsSelectionProvider>
      <ShiftsContent />
    </ShiftsSelectionProvider>
    /* COACHMARK DISABLED - kept for future reference
    </ShiftsCoachmarkProvider>
    */
  );
};

export default Shifts;
