'use client';

import React, { useCallback, useEffect, useState, useMemo } from 'react';
import { Box, Button, Stack, Typography, useTheme, IconButton, CircularProgress } from '@mui/material';
import { HEADER } from '@/layouts/config-layout';
import TableControlBar from '@/shared/components/table/table-control-bar';
import AbsenceTabs from '@/shared/components/tabs/tabs-custom';
import { TableType } from '@/shared/types/common';
import { useAbsenceUsagerTabs } from '../hooks/use-absence-tabs';
import { useAbsenceUsagerTable } from '../hooks/use-absence-table';
import AbsenceForm from './absence-new-view';
import AbsenceTableRow from './absence-table-row';
import TableManager from '@/shared/components/table/table-manager';
import { ScrollBox, WhiteIconButtonStyle } from '@/shared/theme/css';
import {
  DEFAULT_ABSENCE_TABLE_HEAD,
  DEFAULT_ABSENCE_NONTREATED_TABLE_HEAD,
  INITIAL_ABSENCE_DATA,
  TREATED_STATES,
  NON_TREATED_STATES,
  getRHAbsenceStatut,
  getAbsenceTypeLabel,
  getRequestTypeLabel,
} from '@/shared/_mock/_rhAbsence';
import GenericAbsenceView from '@/shared/components/absence/generic-absence-view';
import FontAwesome from '@/shared/components/fontawesome';
import { faCalendar, faSquarePlus } from '@fortawesome/free-solid-svg-icons';
import CustomTooltip from '@/shared/components/tooltips/tooltip-custom';
import { IRHAbsence } from '@/shared/types/absence-rh';
import AbsenceCalendar from '../components/absence-calendar';
import { UnsavedChangesDialog } from '@/shared/components/dialog/UnsavedChangesDialog';
import { DriverAbsenceStatus } from '@/shared/types/driver-absence';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import { useRHAbsenceStore } from '@/shared/api/stores/hr-service/rhAbsence';
import { enqueueSnackbar } from 'notistack';
import { useAbsenceFilters } from '../hooks/use-absence-filters';

// Debounce hook with proper typing
function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

export default function AbsenceRHListView() {
  const theme = useTheme();
  const [openCalendar, setOpenCalendar] = React.useState(false);
  const [showUntreatedSection, setShowUntreatedSection] = useState(true);
  const [showTreatedSection, setShowTreatedSection] = useState(true);

  // Zustand store
  const {
    loading,
    error,
    absences,
    fetchTraitedAbsences,
    fetchNonTraitedAbsences,
    updateAbsenceStatus,
    exportLoading,
    exportError,
    startExport,
    downloadExport,
    allUsers,
    getCollaboratorsForAuthorization,
  } = useRHAbsenceStore();

  const collaborators = getCollaboratorsForAuthorization();
  const getCollaboratorNameById = React.useCallback((id: string | null | undefined): string => {
    if (!id) return '-';
    const collab = collaborators.find(c => c.id === id);
    if (collab) {
      return collab.label;
    }
    
    const user = allUsers.find(u => u.id === id);
    if (user) {
      return user.label;
    }
  
    if (!/^\d+$/.test(id)) {
      return id;
    }
  
    return '-';
  }, [collaborators, allUsers]);

  const {
    traitedFilters,
    nonTraitedFilters,
    buildApiFilters,
    handleFilterChange,
    resetFilters,
    resetAllFilters
  } = useAbsenceFilters();

  // Separate pagination states for each table
  const [nonTraitedPage, setNonTraitedPage] = useState(0);
  const [nonTraitedRowsPerPage, setNonTraitedRowsPerPage] = useState(5);
  const [traitedPage, setTraitedPage] = useState(0);
  const [traitedRowsPerPage, setTraitedRowsPerPage] = useState(5);

  // Zustand store
  const {
    tabs,
    activeTab,
    handleTabClose,
    handleTabChange,
    handleTabAdd,
    handleEdit,
    handleView,
    handleCancel,
    setTabHasUnsavedChanges,
    showConfirmDialog,
    setShowConfirmDialog,
    handleConfirmDialogAction,
    updateTabContent,
  } = useAbsenceUsagerTabs();

  const {
    table,
    tableHead,
    notFound,
    handleResetColumns,
    handleColumnsChange,
    handleSave,
  } = useAbsenceUsagerTable();

  // Debounce filters to prevent multiple requests
  const debouncedNonTraitedFilters = useDebounce(nonTraitedFilters, 300);
  const debouncedTraitedFilters = useDebounce(traitedFilters, 300);

  // Combined fetch function to prevent duplicate logic
  const fetchAbsenceData = useCallback(async (
    isTraited: boolean,
    page: number,
    size: number,
    filters: typeof nonTraitedFilters | typeof traitedFilters
  ) => {
    try {
      const apiFilters = buildApiFilters({ page, size }, isTraited);
      if (isTraited) {
        await fetchTraitedAbsences(apiFilters);
      } else {
        await fetchNonTraitedAbsences(apiFilters);
      }
    } catch (error) {
      enqueueSnackbar('Erreur lors du chargement des données', { variant: 'error' });
    }
  }, [buildApiFilters, fetchTraitedAbsences, fetchNonTraitedAbsences]);

  // Handle filter reset
  const handleResetFilters = useCallback(() => {
    setNonTraitedPage(0);
    setTraitedPage(0);
    resetAllFilters();
    // Force reload both tables with minimal params - no requestType filter
    fetchNonTraitedAbsences({ page: 0, size: nonTraitedRowsPerPage });
    fetchTraitedAbsences({ page: 0, size: traitedRowsPerPage });
  }, [resetAllFilters, fetchNonTraitedAbsences, fetchTraitedAbsences, nonTraitedRowsPerPage, traitedRowsPerPage]);

  // Effect to handle filter changes for non-treated list
  useEffect(() => {
    const filters = buildApiFilters({ page: nonTraitedPage, size: nonTraitedRowsPerPage }, false);
    fetchNonTraitedAbsences(filters);
  }, [nonTraitedFilters, nonTraitedPage, nonTraitedRowsPerPage, buildApiFilters, fetchNonTraitedAbsences]);

  // Effect to handle filter changes for treated list
  useEffect(() => {
    const filters = buildApiFilters({ page: traitedPage, size: traitedRowsPerPage }, true);
    fetchTraitedAbsences(filters);
  }, [traitedFilters, traitedPage, traitedRowsPerPage, buildApiFilters, fetchTraitedAbsences]);

  // Handle pagination change for non-treated table
  const handleNonTraitedPageChange = useCallback((event: React.MouseEvent<HTMLButtonElement> | null, newPage: number) => {
    setNonTraitedPage(newPage);
  }, []);

  // Handle rows per page change for non-treated table
  const handleNonTraitedRowsPerPageChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    const newSize = parseInt(event.target.value, 10);
    setNonTraitedRowsPerPage(newSize);
    setNonTraitedPage(0);
  }, []);

  // Handle pagination change for treated table
  const handleTraitedPageChange = useCallback((event: React.MouseEvent<HTMLButtonElement> | null, newPage: number) => {
    setTraitedPage(newPage);
  }, []);

  // Handle rows per page change for treated table
  const handleTraitedRowsPerPageChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    const newSize = parseInt(event.target.value, 10);
    setTraitedRowsPerPage(newSize);
    setTraitedPage(0);
  }, []);

  // Map and transform non-treated absences data to display format
  const nonTraitedData = React.useMemo(() => {
    const beforeFilter = absences.nonTraited.content || [];
    
    // Show both ABSENCE and LEAVE requests (no filtering by requestType anymore)
    const afterFilter = beforeFilter;
    
    if (afterFilter.length === 0) {
      return [];
    }

    const mapped = afterFilter.map(absence => {
      // Determine user type based on functionType from backend
      const functionType = absence.functionType || absence.user?.functionType;
      const userType: 'chauffeur' | 'sédentaire' = functionType === 'DRIVER' ? 'chauffeur' : 'sédentaire';

      // Map justification - use justificationFileUrl directly
      const justificatif = absence.justificationFileUrl || undefined;

      return {
        ...absence,
        id: String(absence.id),
        numeroEnregistrement: `${absence.requestType === 'LEAVE' ? 'CONG' : 'ABS'}-${String(absence.id).padStart(4, '0')}`,
        nomChauffeur: absence.user ? `${absence.user.firstName} ${absence.user.lastName}` : 'Utilisateur inconnu',
        requestTypeLabel: getRequestTypeLabel(absence.requestType),
        typeAbsence: absence.absenceType || absence.leaveType,
        typeAbsenceLabel: getAbsenceTypeLabel((absence.absenceType || absence.leaveType || ''), absence.requestType || 'ABSENCE'),
        dateDebut: absence.startDate,
        dateFin: absence.endDate,
        statut: absence.state,
        justificatif,
        affecteTrajet: absence.affectedToTrip,
        modeReception: absence.receivingMethod,
        nbrHeures: absence.hoursCount || absence.numberOfDays * 8,
        // ✅ Use name from backend if available, fallback to ID mapping
        validerPar: absence.validatedByName || getCollaboratorNameById(absence.validatedBy),
        autorisePar: absence.authorizedByName || getCollaboratorNameById(absence.authorizedBy),
        departement: absence.user?.departmentName || 'N/A',
        type: userType,
        observations: absence.observations,
        forecastDate: absence.forecastDate,
        comment: absence.comment,
        submittedAt: absence.submittedAt,
        processedAt: absence.processedAt,
        receivingMethod: absence.receivingMethod,
        requestType: absence.requestType,
      };
    });
    
    return mapped;
  }, [absences.nonTraited.content, getCollaboratorNameById]);
    
  const traitedData = React.useMemo(() => {
    const beforeFilter = absences.traited.content || [];
    
    // Show both ABSENCE and LEAVE requests (no filtering by requestType anymore)
    const afterFilter = beforeFilter;
    
    if (afterFilter.length === 0) {
      return [];
    }

    const mapped = afterFilter.map(absence => {
      const functionType = absence.functionType || absence.user?.functionType;
      const userType: 'chauffeur' | 'sédentaire' = functionType === 'DRIVER' ? 'chauffeur' : 'sédentaire';
      
      // Map justification - use justificationFileUrl directly
      const justificatif = absence.justificationFileUrl || undefined;

      return {
        ...absence,
        id: String(absence.id),
        numeroEnregistrement: `${absence.requestType === 'LEAVE' ? 'CONG' : 'ABS'}-${String(absence.id).padStart(4, '0')}`,
        nomChauffeur: absence.user ? `${absence.user.firstName} ${absence.user.lastName}` : 'Utilisateur inconnu',
        requestTypeLabel: getRequestTypeLabel(absence.requestType),
        typeAbsence: absence.absenceType || absence.leaveType,
        typeAbsenceLabel: getAbsenceTypeLabel((absence.absenceType || absence.leaveType || ''), absence.requestType || 'ABSENCE'),
        dateDebut: absence.startDate,
        dateFin: absence.endDate,
        statut: absence.state,
        justificatif,
        affecteTrajet: absence.affectedToTrip,
        modeReception: absence.receivingMethod,
        nbrHeures: absence.hoursCount || absence.numberOfDays * 8,
        validerPar: getCollaboratorNameById(absence.validatedBy),
        autorisePar: getCollaboratorNameById(absence.authorizedBy),
        departement: absence.user?.departmentName || 'N/A',
        type: userType,
        observations: absence.observations,
        forecastDate: absence.forecastDate,
        comment: absence.comment,
        submittedAt: absence.submittedAt,
        processedAt: absence.processedAt,
        receivingMethod: absence.receivingMethod,
        requestType: absence.requestType,
      };
    });
    
    return mapped;
  }, [absences.traited.content, getCollaboratorNameById]);

  // Combine all absences for the calendar
  const allAbsences = React.useMemo(() => {
    return [...nonTraitedData, ...traitedData];
  }, [nonTraitedData, traitedData]);

  // Handle status change
  const handleStatusChange = useCallback(async (row: IRHAbsence, newStatus: string, field: keyof IRHAbsence) => {
    try {
      const comment = newStatus === 'Approved' ? 'AcceptedByRH' : newStatus === 'Rejected' ? 'RejectedByRH' : 'UpdatedByRH';
      await updateAbsenceStatus(row.id, newStatus, comment);
      enqueueSnackbar('Statut mis à jour avec succès', { variant: 'success' });
    } catch (error) {
      enqueueSnackbar('Erreur lors de la mise à jour du statut', { variant: 'error' });
    }
  }, [updateAbsenceStatus]);

  // Auto-change status from "Non traité" to "En cours" when editing
  const handleEditWithStatusChange = useCallback(async (row: IRHAbsence) => {
    const currentStatus = row.statut || row.state;
    const isUnprocessed = currentStatus === 'Unprocessed' || 
                          currentStatus === 'NON_TRAITE' || 
                          currentStatus === 'Non traité' ||
                          currentStatus === 'non_traite';

    if (isUnprocessed) {
      const updatedRow = {
        ...row,
        statut: 'In_progress',
        state: 'In_progress'
      };
      
      handleEdit(updatedRow);
      
      handleStatusChange(row, 'In_progress', 'statut').catch(() => {
        enqueueSnackbar('Erreur lors de la mise à jour automatique du statut', { variant: 'error' });
      });
    } else {
      handleEdit(row);
    }
  }, [handleEdit, handleStatusChange, enqueueSnackbar]);

  const renderRow = useCallback((row: IRHAbsence) => {
    return (
      <AbsenceTableRow
        key={row.id}
        dense={table.dense}
        row={row}
        handleEdit={handleEditWithStatusChange}
        handleDetails={handleView}
        selected={table.selected.includes(String(row.id))}
        onSelectRow={() => table.onSelectRow(String(row.id))}
        columns={DEFAULT_ABSENCE_NONTREATED_TABLE_HEAD.slice(0, -1)}
        onStatusChange={(r, status, field) => handleStatusChange(r, status, field)}
        isTraiteTable={false}
      />
    );
  }, [table, handleEditWithStatusChange, handleView, handleStatusChange]);

  const renderTreatedRow = useCallback((row: IRHAbsence) => {
    return (
      <AbsenceTableRow
        key={row.id}
        dense={table.dense}
        row={row}
        handleEdit={handleEdit}
        handleDetails={handleView}
        selected={table.selected.includes(String(row.id))}
        onSelectRow={() => table.onSelectRow(String(row.id))}
        columns={DEFAULT_ABSENCE_TABLE_HEAD.slice(0, -1)}
        onStatusChange={(r, status, field) => handleStatusChange(r, status, field)}
        isTraiteTable={true}
      />
    );
  }, [table, handleEdit, handleView, handleStatusChange]);

  const activeTabData = React.useMemo(() => {
    return tabs.find((tab) => tab.id === activeTab);
  }, [tabs, activeTab]);

  // Edit handler that auto-changes status for non-treated absences
  const editHandlerForActiveTab = React.useCallback((absence: IRHAbsence) => {
    const currentStatus = absence.statut || absence.state;
    const isUnprocessed = currentStatus === 'Unprocessed' || 
                          currentStatus === 'NON_TRAITE' || 
                          currentStatus === 'Non traité' ||
                          currentStatus === 'non_traite';
    
    if (isUnprocessed) {
      handleEditWithStatusChange(absence);
    } else {
      handleEdit(absence);
    }
  }, [handleEdit, handleEditWithStatusChange]);

  useEffect(() => {
    setShowTreatedSection(activeTab === 'list');
  }, [activeTab]);

  const handleTreatedTabChange = useCallback((newActiveTab: string) => {
    setShowUntreatedSection(newActiveTab === "list")
  }, [])

  // Debug: Log local filter changes
  useEffect(() => {
    
  }, [nonTraitedFilters, traitedFilters]);

  // Don't show global loading state for filters - let tables handle their own loading
  // Only show global loading if there's no data at all (initial load)
  const shouldShowGlobalLoading = loading && 
    (!absences.nonTraited.content || absences.nonTraited.content.length === 0) && 
    (!absences.traited.content || absences.traited.content.length === 0);

  // Export handler
  const handleStartExport = async (isTreatedList: boolean) => {
    try {
      // Use the correct filters based on which list is being exported
      const exportFilters = buildApiFilters({ 
        page: 0, 
        size: 999999 // Large size to export all
      }, isTreatedList);
      
      const result = await startExport(exportFilters);
      
      if (result.success && result.exportPath) {
        enqueueSnackbar(result.message, { variant: 'success' });
        
        // Optionally auto-download the file
        setTimeout(async () => {
          try {
            const downloadResult = await downloadExport(result.exportPath!);
            if (downloadResult.success) {
              enqueueSnackbar(downloadResult.message, { variant: 'success' });
            } else {
              enqueueSnackbar(downloadResult.message, { variant: 'error' });
            }
          } catch (error) {
            enqueueSnackbar('Échec du téléchargement automatique', { variant: 'error' });
          }
        }, 2000); // Wait 2 seconds for export to complete
      } else {
        enqueueSnackbar(result.message, { variant: 'error' });
      }
    } catch (error) {
      enqueueSnackbar('Échec de l\'export', { variant: 'error' });
    }
  };

  // Re-create export actions when filters change
  const exportActions = useMemo(() => [
    {
      label: 'Exporter la liste non traitée',
      action: () => handleStartExport(false),
    },
    {
      label: 'Exporter la liste traitée',
      action: () => handleStartExport(true),
    },
  ], [handleStartExport]);

  if (shouldShowGlobalLoading) {
    return (
      <Box 
        sx={{ 
          display: 'flex', 
          justifyContent: 'center', 
          alignItems: 'center', 
          height: '200px' 
        }}
      >
        <CircularProgress />
        <Typography sx={{ ml: 2 }}>Chargement des absences...</Typography>
      </Box>
    );
  }

  // Show error state
  if (error) {
    return (
      <Box sx={{ p: 2 }}>
        <Typography color="error">
          Erreur: {error}
        </Typography>
        <Button 
          onClick={() => {
            fetchNonTraitedAbsences({ page: 0, size: nonTraitedRowsPerPage });
            fetchTraitedAbsences({ page: 0, size: traitedRowsPerPage });
          }}
          sx={{ mt: 1 }}
        >
          Réessayer
        </Button>
      </Box>
    );
  }

  return (
    <ScrollBox sx={{ height: `calc(100vh - ${HEADER.H_DESKTOP + 20}px)` }}>
      <ConditionalComponent isValid={showUntreatedSection}>
        <Box>
          <Stack
            direction="row"
            alignItems="center"
            justifyContent="flex-end"
            spacing={{ xs: 0.5, sm: 1 }}
          >
            <CustomTooltip title="Calendrier global des absences" arrow>
              <IconButton
                onClick={() => setOpenCalendar(true)}
                sx={{
                  ...WhiteIconButtonStyle,
                  padding: 0.75,
                }}
              >
                <FontAwesome icon={faCalendar} width={18} />
              </IconButton>
            </CustomTooltip>
            <TableControlBar
              type={TableType.AbsenceUsager}
              handleTabAdd={handleTabAdd}
              activeTab={activeTab}
              onResetFilters={handleResetFilters}
              onResetColumns={handleResetColumns}
              onColumnsChange={handleColumnsChange}
              initialColumns={DEFAULT_ABSENCE_NONTREATED_TABLE_HEAD.slice(0, -1)}
              onFilters={(key, value, condition) => handleFilterChange(key, value, condition, false)}
              filteredData={nonTraitedData}
              useBackendExport={true}
              exportOptions={exportActions}
            />
          </Stack>

          <AbsenceCalendar
            open={openCalendar}
            onClose={() => setOpenCalendar(false)}
            absences={allAbsences}
            onViewAbsence={handleView}
          />

          <Typography
            variant="h5"
            sx={{
              mb: 2,
              color: 'primary.main',
              fontWeight: (theme) => theme.typography.fontWeightBold,
            }}
          >
            Liste des absences et congés non traités ({absences.nonTraited.totalElements || 0})
          </Typography>
          <AbsenceTabs
            type={'Demandes non traitées'}
            tabs={tabs}
            activeTab={activeTab}
            handleTabChange={handleTabChange}
            handleTabClose={handleTabClose}
          />
          {activeTab === 'list' ? (
            <TableManager
              filteredData={nonTraitedData}
              table={table}
              tableHead={DEFAULT_ABSENCE_NONTREATED_TABLE_HEAD}
              notFound={nonTraitedData.length === 0}
              filters={nonTraitedFilters}
              onFilterChange={(key, value, condition) => handleFilterChange(key, value, condition, false)}
              renderRow={renderRow}
              fixedHeight="calc(100vh - 340px)"
              count={absences.nonTraited.totalElements || 0}
              page={nonTraitedPage}
              rowsPerPage={nonTraitedRowsPerPage}
              onPageChange={handleNonTraitedPageChange}
              onRowsPerPageChange={handleNonTraitedRowsPerPageChange}
              loading={loading}
            />
          ) : (
            <AbsenceForm
              key={activeTab}
              absence={activeTabData?.content as IRHAbsence}
              mode={activeTabData?.mode || 'view'}
              onSave={handleSave}
              onClose={(forceClose) => handleCancel(activeTab, forceClose)}
              onEdit={editHandlerForActiveTab}
              updateTabContent={updateTabContent}
              tabId={activeTab}
            />
          )}
        </Box>
      </ConditionalComponent>
      <ConditionalComponent isValid={showTreatedSection}>
        <Box>
          <Typography
            variant="h5"
            sx={{
              mb: 2,
              color: 'primary.main',
              fontWeight: (theme) => theme.typography.fontWeightBold,
            }}
          >
            Liste des absences et congés traités ({absences.traited.totalElements || 0})
          </Typography>
          <TableManager
            filteredData={traitedData}
            table={table}
            tableHead={DEFAULT_ABSENCE_TABLE_HEAD}
            notFound={traitedData.length === 0}
            filters={traitedFilters}
            onFilterChange={(key, value, condition) => handleFilterChange(key, value, condition, true)}
            renderRow={renderTreatedRow}
            fixedHeight="calc(100vh - 340px)"
            count={absences.traited.totalElements || 0}
            page={traitedPage}
            rowsPerPage={traitedRowsPerPage}
            onPageChange={handleTraitedPageChange}
            onRowsPerPageChange={handleTraitedRowsPerPageChange}
            loading={loading}
          />
        </Box>
      </ConditionalComponent>
      <UnsavedChangesDialog
        open={showConfirmDialog}
        onClose={() => setShowConfirmDialog(false)}
        onConfirm={handleConfirmDialogAction}
        onCancel={() => setShowConfirmDialog(false)}
      />
    </ScrollBox>
  );
}