"use client"
import { useEffect, useState, useCallback, useMemo } from "react"
import React from "react"
import { Box, Grid, Button, Typography, IconButton, Tooltip, CircularProgress } from "@mui/material"
import { Departements } from "@/shared/types/etablissement"
import ActionButtons from "@/shared/components/form/buttons-action"
import AttendanceSheetCher from "../components/attendance-sheet-cher"
import AttendanceSheetNotCher from "../components/attendance-sheet-not-cher"
import ExportModal from "./export-modal"
import FontAwesome from "@/shared/components/fontawesome"
import { faFileExport, faPenToSquare } from "@fortawesome/free-solid-svg-icons"
import type { ModeType } from "@/shared/types/common"
import MultiSectionContainer from "@/shared/components/form/multiForm-container"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import {
  AttendanceSheet,
  AttendanceSheetWithRouteSheets,
  BatchUpdatePayload,
  IAttendanceNotCher,
  IAttendanceSheetCher,
  MonthsString,
  RouteSheetDTO
} from "@/shared/types/attendance-sheet"
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
import { fr } from 'date-fns/locale'
import { useAttendanceSheetStore } from "@/shared/api/stores/attendanceSheetStore"
import { useSnackbar } from 'notistack'
import { ConcernedTrip } from "@/shared/types/absence"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"


interface PendingChange {
  passengerId: number;
  date: string;
  tripType: 'A' | 'R';
  isAbsent: boolean;
}

type TabData = IAttendanceNotCher | IAttendanceSheetCher

interface SheetTab {
  id: number;
  data: TabData;
  isReadOnly?: boolean;
}

interface AttendanceSheetParentProps {
  onReturn: () => void;
  mode?: ModeType;
  vacation?: AttendanceSheetWithRouteSheets;
  initialDepartement?: string;
  onClose: (isSaved: boolean) => void;
  attendance: Record<string, Record<string, boolean>> | Record<number, Record<string, Record<string, boolean>>>;
  updateTabAttendance: (tabId: string, attendance: Record<string, Record<string, boolean>> | Record<number, Record<string, Record<string, boolean>>>) => void;
  tabId: string;
  onEdit?: () => void;
  showEditButton?: boolean;
}

function MultiSectionForm({
  onReturn,
  mode = "edit",
  vacation,
  initialDepartement = Departements.Cher,
  onClose,
  attendance,
  updateTabAttendance,
  tabId,
  onEdit,
  showEditButton = false,
}: AttendanceSheetParentProps) {
  const { enqueueSnackbar } = useSnackbar();
  const [tabs, setTabs] = useState<SheetTab[]>([]);
  const [exportModalOpen, setExportModalOpen] = useState(false);
  const [pendingChanges, setPendingChanges] = useState<PendingChange[]>([]);
  const [isSaving, setIsSaving] = useState(false);
  const [initialStates, setInitialStates] = useState<Record<string, boolean>>({});
  const { updateAttendanceStatusBatch, exportAttendanceSheetPdf } = useAttendanceSheetStore();
  const WEEKDAYS = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'] as const;

  const monthNumberToName = useCallback((month: number): string => {
    return Object.values(MonthsString)[month - 1] || "";
  }, []);

  const handleCancelChanges = useCallback(() => {
    if (pendingChanges.length > 0 && mode !== 'view') {

      setPendingChanges([]);

      if (initialDepartement === 'cher') {

        const restoredAttendance: Record<number, Record<string, Record<string, boolean>>> = {};

        tabs.forEach((tab, tabIndex) => {
          restoredAttendance[tab.id] = {};
          const sheet = vacation?.routeSheets?.[tabIndex];

          if (sheet && sheet.passengers) {
            sheet.passengers.forEach((passenger: any) => {
              tab.data.calendar?.days?.forEach((day, dayIndex) => {
                const weekIndex = Math.floor(dayIndex / 7);
                const weekDayIndex = dayIndex % 7;
                const weekday = WEEKDAYS[weekDayIndex];

                if (weekday && day.passengerStatuses && weekDayIndex < 5) {
                  if (!restoredAttendance[tab.id][weekday]) {
                    restoredAttendance[tab.id][weekday] = {};
                  }

                  const dayKey = `${sheet.year}-${String(sheet.month).padStart(2, '0')}-${String(day.dayOfMonth).padStart(2, '0')}`;
                  const keyA = `${passenger.id}-${dayKey}-A`;
                  const keyR = `${passenger.id}-${dayKey}-R`;

                  restoredAttendance[tab.id][weekday][`${weekIndex}-0`] = initialStates[keyA] !== undefined ? initialStates[keyA] : true;
                  restoredAttendance[tab.id][weekday][`${weekIndex}-1`] = initialStates[keyR] !== undefined ? initialStates[keyR] : true;
                }
              });
            });
          }
        });

        updateTabAttendance(tabId, restoredAttendance);
      } else {
        const restoredAttendance: Record<string, Record<string, boolean>> = {};
        const sheet = vacation?.routeSheets?.[0];

        if (sheet) {
          tabs[0]?.data.calendar?.days?.forEach(day => {
            if (!day.weekend && day.dayOfMonth) {
              restoredAttendance[`${day.dayOfMonth}`] = {};

              if (day.passengerStatuses) {
                Object.entries(day.passengerStatuses).forEach(([passengerId, status]: [string, any]) => {
                  const dayKey = `${sheet.year}-${String(sheet.month).padStart(2, '0')}-${String(day.dayOfMonth).padStart(2, '0')}`;
                  const keyA = `${passengerId}-${dayKey}-A`;
                  const keyR = `${passengerId}-${dayKey}-R`;

                  restoredAttendance[`${day.dayOfMonth}`][`${passengerId}-A`] = initialStates[keyA] !== undefined ? initialStates[keyA] : true;
                  restoredAttendance[`${day.dayOfMonth}`][`${passengerId}-R`] = initialStates[keyR] !== undefined ? initialStates[keyR] : true;
                });
              }
            }
          });
        }

        updateTabAttendance(tabId, restoredAttendance);
      }

      enqueueSnackbar('Modifications annulées', { variant: 'info' });
      onClose(false);
    } else {
      onClose(false);
    }
  }, [pendingChanges.length, onClose, mode, initialStates, tabs, initialDepartement, updateTabAttendance, tabId, vacation?.routeSheets, enqueueSnackbar]);


  const CustomCancelButton = useMemo(() => (
    <Button
      variant="outlined"
      onClick={handleCancelChanges}
      sx={{
        textTransform: "none",
        color: "text.secondary",
        borderColor: "divider",
        "&:hover": {
          borderColor: "error.main",
          color: "error.main",
        },
      }}
    >
      <ConditionalComponent
        isValid={pendingChanges.length > 0}
        defaultComponent={
          <ConditionalComponent
            isValid={mode === 'edit' && showEditButton === false}
            defaultComponent="Annuler "
          >
            Retour à la liste
          </ConditionalComponent>
        }
      >
        Annuler ({pendingChanges.length})
      </ConditionalComponent>
    </Button>
  ), [handleCancelChanges, pendingChanges.length]);

  useEffect(() => {
    if (vacation?.routeSheets && Array.isArray(vacation.routeSheets) && vacation.routeSheets.length > 0) {
      const initialTabs = vacation.routeSheets.map((sheet: RouteSheetDTO, idx: number) => ({
        id: idx,
        data: {
          departement: sheet.departmentName,
          month: monthNumberToName(sheet.month),
          year: String(sheet.year),
          circuit: sheet.circuitName,
          etablissement: sheet.establishment?.establishmentName || "",
          driver: sheet.driver ? `${sheet.driver.firstName} ${sheet.driver.lastName}` : "Non assigné",
          establishment: sheet.establishment || null,
          adresse: sheet.establishment?.address ?
            `${sheet.establishment.address.street}, ${sheet.establishment.address.zipCode} ${sheet.establishment.address.city}` : "",
          telephone: sheet.establishment?.fax || "",
          passengers: sheet.passengers || [],
          nomResponsable: sheet.establishment?.establishmentManager
            ? `${sheet.establishment.establishmentManager.firstName} ${sheet.establishment.establishmentManager.lastName}`
            : "",
          calendar: {
            ...sheet.calendar,
            days: sheet.calendar?.days?.map(day => {
              return {
                ...day,
                passengerStatuses: day.passengerStatuses || {}
              };
            }) || []
          },
        },
      }));

      setTabs(initialTabs);

      const initialStatesMap: Record<string, boolean> = {};
      vacation.routeSheets.forEach(sheet => {
        sheet.calendar?.days?.forEach(day => {
          if (day.passengerStatuses) {
            Object.entries(day.passengerStatuses).forEach(([passengerId, status]: [string, any]) => {
              const dayKey = `${sheet.year}-${String(sheet.month).padStart(2, '0')}-${String(day.dayOfMonth).padStart(2, '0')}`;

              const keyA = `${passengerId}-${dayKey}-A`;
              initialStatesMap[keyA] = status?.outbound !== undefined ? status.outbound : true;

              const keyR = `${passengerId}-${dayKey}-R`;
              initialStatesMap[keyR] = status?.return !== undefined ? status.return : true;
            });
          }
        });
      });
      setInitialStates(initialStatesMap);
    }
  }, [vacation?.routeSheets, monthNumberToName]);

  const handleAttendanceUpdate = useCallback(async (
    passengerId: number,
    date: string,
    isAbsent: boolean,
    tripType?: 'A' | 'R'
  ): Promise<void> => {
    if (!tripType) return Promise.resolve();

    const key = `${passengerId}-${date}-${tripType}`;
    const initialValue = initialStates[key] !== undefined ? !initialStates[key] : false;

    setPendingChanges(prev => {
      const existingIndex = prev.findIndex(
        change => change.passengerId === passengerId &&
          change.date === date &&
          change.tripType === tripType
      );

      if (isAbsent === initialValue) {
        if (existingIndex !== -1) {
          return prev.filter((_, index) => index !== existingIndex);
        }
        return prev;
      }

      const newChange: PendingChange = {
        passengerId,
        date,
        tripType,
        isAbsent
      };

      if (existingIndex !== -1) {
        const newChanges = [...prev];
        newChanges[existingIndex] = newChange;
        return newChanges;
      }

      return [...prev, newChange];
    });

    return Promise.resolve();
  }, [initialStates]);

  const handleSaveAll = useCallback(async () => {
    try {
      setIsSaving(true);

      if (pendingChanges.length === 0) {
        enqueueSnackbar('Aucun changement à enregistrer', { variant: 'info' });
        return;
      }

      const convertMonthToNumber = (monthStr: string): string => {
        const months: { [key: string]: string } = {
          'Janvier': '01', 'Fevrier': '02', 'Mars': '03', 'Avril': '04',
          'Mai': '05', 'Juin': '06', 'Juillet': '07', 'Aout': '08',
          'Septembre': '09', 'Octobre': '10', 'Novembre': '11', 'Decembre': '12'
        };
        return months[monthStr] || monthStr;
      };

      const groupedChanges = new Map<string, { passengerId: number; date: string; concernedTrips: ConcernedTrip[] }>();

      pendingChanges.forEach(change => {
        const [year, month, day] = change.date.split('-');
        const formattedDate = `${year}-${convertMonthToNumber(month)}-${day.padStart(2, '0')}`;
        const key = `${change.passengerId}-${formattedDate}`;

        if (!groupedChanges.has(key)) {
          groupedChanges.set(key, {
            passengerId: change.passengerId,
            date: formattedDate,
            concernedTrips: []
          });
        }

        const existingChange = groupedChanges.get(key)!;

        const keyA = `${change.passengerId}-${change.date}-A`;
        const keyR = `${change.passengerId}-${change.date}-R`;

        const allerChange = pendingChanges.find(c =>
          c.passengerId === change.passengerId &&
          c.date === change.date &&
          c.tripType === 'A'
        );
        const retourChange = pendingChanges.find(c =>
          c.passengerId === change.passengerId &&
          c.date === change.date &&
          c.tripType === 'R'
        );

        let isAllerAbsent = false;
        let isRetourAbsent = false;

        if (allerChange) {
          isAllerAbsent = allerChange.isAbsent;
        } else {
          const initialAllerPresent = initialStates[keyA] !== undefined ? initialStates[keyA] : true;
          isAllerAbsent = !initialAllerPresent;
        }

        if (retourChange) {
          isRetourAbsent = retourChange.isAbsent;
        } else {
          const initialRetourPresent = initialStates[keyR] !== undefined ? initialStates[keyR] : true;
          isRetourAbsent = !initialRetourPresent;
        }

        const finalConcernedTrips: ConcernedTrip[] = [];
        if (isAllerAbsent) {
          finalConcernedTrips.push(ConcernedTrip.Outbound);
        }
        if (isRetourAbsent) {
          finalConcernedTrips.push(ConcernedTrip.Return);
        }

        existingChange.concernedTrips = finalConcernedTrips;
      });

      const changes = Array.from(groupedChanges.values());

      const payload = {
        attendanceSheetId: Number(vacation?.id) || 5,
        changes: changes
      };

      await updateAttendanceStatusBatch(payload);

      setPendingChanges([]);
      enqueueSnackbar('Les modifications ont été enregistrées avec succès', {
        variant: 'success'
      });
      onClose(true);
    } catch (error) {
      console.error('Erreur lors de la sauvegarde:', error);
      enqueueSnackbar('Erreur lors de la sauvegarde des modifications', {
        variant: 'error'
      });
    } finally {
      setIsSaving(false);
    }
  }, [pendingChanges, vacation?.id, updateAttendanceStatusBatch, enqueueSnackbar, onClose, initialStates]);

  const handleFormChange = useCallback((tabId: number, newData: TabData) => {
    setTabs((prevTabs) => prevTabs.map((tab) => (
      tab.id === tabId ? { ...tab, data: newData } : tab
    )));
  }, []);

  const handleAttendanceChangeNotCher = useCallback(
    (newAttendance: Record<string, Record<string, boolean>>) => {
      updateTabAttendance(tabId, newAttendance);
    },
    [updateTabAttendance, tabId],
  );

  const handleAttendanceChangeCher = useCallback(
    (newAttendance: Record<number, Record<string, Record<string, boolean>>>) => {
      updateTabAttendance(tabId, newAttendance);
    },
    [updateTabAttendance, tabId],
  );

  const exportSheets = useMemo(
    () => tabs.map((tab) => ({
      id: `Feuille-${tab.id}`,
      name: `Feuille ${tab.id + 1} - ${"etablissement" in tab.data ? tab.data.etablissement : ""} (${"mois" in tab.data && "annee" in tab.data ? `${tab.data.mois}/${tab.data.annee}` : ""
        })`,
    })),
    [tabs],
  );

  const handleExportPdf = useCallback(async () => {
    try {
      if (!vacation?.id || !vacation.routeSheets?.[0]) {
        enqueueSnackbar('Données manquantes pour l\'export', { variant: 'error' });
        return;
      }

      const sheet = vacation.routeSheets[0];
      await exportAttendanceSheetPdf(
        Number(vacation.id),
        sheet.month,
        sheet.year
      );

      enqueueSnackbar('Export PDF généré avec succès', { variant: 'success' });
    } catch (error) {
      console.error('Erreur lors de l\'export PDF:', error);
      enqueueSnackbar('Erreur lors de l\'export PDF', { variant: 'error' });
    }
  }, [vacation, exportAttendanceSheetPdf, enqueueSnackbar]);

  const exportButton = useMemo(
    () => (
      <Button
        variant="outlined"
        onClick={handleExportPdf}
        endIcon={<FontAwesome icon={faFileExport} width={18} />}
        sx={{
          textTransform: "none",
          color: "text.secondary",
          borderColor: "divider",
          "&:hover": {
            borderColor: "primary.main",
            color: "primary.main",
          },
        }}
      >
        Exporter PDF
      </Button>
    ),
    [handleExportPdf],
  );

  if (!tabs.length) {
    return (
      <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '200px' }}>
        <Typography>Aucune donnée disponible</Typography>
      </Box>
    );
  }

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={fr}>
      <Box sx={{ p: 2, bgcolor: "white" }}>
        <ConditionalComponent
          isValid={showEditButton && mode === 'view'}
          defaultComponent={null}
        >
          <Box sx={{ mb: 2 }}>
            <EditExportButtons
              onEdit={onEdit}
              tooltipTitle="Feuille de présence"
              tableHead={[]}
            />
          </Box>
        </ConditionalComponent>

        <Grid container spacing={4}>
          <ConditionalComponent
            isValid={initialDepartement === 'cher'}
            defaultComponent={
              <AttendanceSheetNotCher
                tabs={tabs as { id: number; data: IAttendanceNotCher; isReadOnly?: boolean }[]}
                tab={tabs[0] as { id: number; data: IAttendanceNotCher; isReadOnly?: boolean }}
                mode={mode}
                handleFormChange={handleFormChange}
                attendance={attendance as Record<string, Record<string, boolean>>}
                onAttendanceChange={handleAttendanceChangeNotCher}
                onAttendanceUpdate={handleAttendanceUpdate}
              />
            }
          >
            <>
              {tabs.map((tab) => (
                <MultiSectionContainer key={tab.id} id={tab.id} title="Feuille">
                  <AttendanceSheetCher
                    tabs={tabs as { id: number; data: IAttendanceSheetCher; isReadOnly?: boolean }[]}
                    tab={tab as { id: number; data: IAttendanceSheetCher; isReadOnly?: boolean }}
                    mode={mode}
                    handleFormChange={handleFormChange}
                    attendance={attendance as Record<number, Record<string, Record<string, boolean>>>}
                    onAttendanceChange={handleAttendanceChangeCher}
                    onAttendanceUpdate={handleAttendanceUpdate}
                  />
                </MultiSectionContainer>
              ))}
            </>
          </ConditionalComponent>
        </Grid>

        <ConditionalComponent
          isValid={pendingChanges.length > 0 && mode !== 'view'}
          defaultComponent={null}
        >
          <Typography
            variant="body2"
            color="warning.main"
            sx={{
              mt: 2,
              mb: 2,
              textAlign: 'center',
              fontStyle: 'italic'
            }}
          >
            {pendingChanges.length} modification{pendingChanges.length > 1 ? 's' : ''} en attente
          </Typography>
        </ConditionalComponent>

        <Grid item xs={12} sx={{ mt: 3 }}>
          <Box display="flex" justifyContent="flex-end" gap={2}>
            {CustomCancelButton}

            <Button
              variant="contained"
              onClick={mode === 'view' ? () => onClose(false) : handleSaveAll}
              disabled={isSaving}
              sx={{
                textTransform: "none",
                boxShadow: "none"
              }}
            >
              <ConditionalComponent isValid={isSaving}>
                <CircularProgress size={15} sx={{ mr: 1 }} />
              </ConditionalComponent>

              <ConditionalComponent
                isValid={mode === 'view'}
                defaultComponent="Enregistrer"
              >
                Fermer
              </ConditionalComponent>
            </Button>
            <ConditionalComponent isValid={mode === 'view'}>
              {exportButton}
            </ConditionalComponent>
          </Box>
        </Grid>

        <ExportModal
          open={exportModalOpen}
          onClose={() => setExportModalOpen(false)}
          onExport={() => void 0}
          sheets={exportSheets}
        />
      </Box>
    </LocalizationProvider>
  );
}

export default React.memo(MultiSectionForm);