'use client';

import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
import { Box, Button, Typography, GlobalStyles, Select, MenuItem } from '@mui/material';
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import frLocale from '@fullcalendar/core/locales/fr';
import { IAppointment } from '@/shared/types/appointment';
import CustomDrawer from '@/shared/components/drawer/custom-drawer';
import { ScheduleToolbar } from '../components/schedule-toolbar';
import CustomTabs from '@/shared/components/tabs/tabs-custom';
import AppointmentTable from '../components/appointment-table';
import AppointmentForm from './appointment-new-view';
import { useAppointmentTabs } from '../hooks/use-appointment-tabs';
import { useAppointmentTable } from '../hooks/use-appointment-table';
import { TableType } from '@/shared/types/common';
import { formatEventForCalendar, renderEventContent } from '../components/calendar-helpers';
import {
  CalendarGlobalStyles,
  calendarStyles,
  drawerStyles,
  calendarHeaderStyles,
  mainContainerStyles
} from '../stytles';
import { DatesSetArg } from '@fullcalendar/core/index.js';
import { AddButton } from '@/shared/components/table/styles';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import CustomTooltip from '@/shared/components/tooltips/tooltip-custom';
import FontAwesome from '@/shared/components/fontawesome';
import { faSquarePlus } from '@fortawesome/free-solid-svg-icons';
import { Stack } from '@mui/system';
import { UnsavedChangesDialog } from '@/shared/components/dialog/UnsavedChangesDialog';

const DRAWER_WIDTH = 580;

interface CalendarHeaderProps {
  currentView: string;
  onViewChange: (view: string) => void;
  onAddNew: () => void;
  currentDate: Date;
}

const CalendarHeader = ({ currentView, onViewChange, onAddNew, currentDate }: CalendarHeaderProps) => {
  const formatDate = (date: Date) => {
    const dateObj = date instanceof Date ? date : new Date(date);
    return new Intl.DateTimeFormat('fr-FR', {
      month: 'long',
      year: 'numeric'
    }).format(dateObj);
  };

  return (
    <Box sx={calendarHeaderStyles.container}>
      <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
        <Select
          value={currentView}
          onChange={(e) => onViewChange(e.target.value as string)}
          size="small"
          sx={calendarHeaderStyles.select}
        >
          <MenuItem value="timeGridDay">Jour</MenuItem>
          <MenuItem value="timeGridWeek">Semaine</MenuItem>
          <MenuItem value="dayGridMonth">Mois</MenuItem>
        </Select>
      </Box>

      <Typography variant="h5" sx={calendarHeaderStyles.title}>
        {formatDate(currentDate)}
      </Typography>

      <CustomTooltip title={"Ajouter Un Nouveau rendez-vous"} arrow>
        <AddButton
          onClick={onAddNew}
          variant="contained"
          endIcon={<FontAwesome icon={faSquarePlus} width={18} />}
        >
          Nouveau rendez-vous
        </AddButton>
      </CustomTooltip>

    </Box>
  );
};

export default function AppointmentView() {
  const [state, setState] = useState({
    isDrawerOpen: false,
    currentDate: new Date(),
    currentView: 'dayGridMonth',
    zoomLevel: 50,
  });

  const calendarRef = useRef<any>(null);

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

  const {
    table,
    filteredData,
    filters,
    tableHead,
    notFound,

    handleFilterChange,
    handleResetFilters,
    handleSave,
  } = useAppointmentTable();

  const updateState = useCallback((updates: Partial<typeof state>) => {
    setState(prev => ({ ...prev, ...updates }));
  }, []);

  const handleDrawerToggle = useCallback(() => {
    updateState({ isDrawerOpen: !state.isDrawerOpen });
    setTimeout(() => {
      const calendarApi = calendarRef.current?.getApi();
      if (calendarApi) {
        calendarApi.updateSize();
      }
    }, 300);
  }, [state.isDrawerOpen, updateState]);

  const handleDateChange = useCallback((date: Date) => {
    updateState({ currentDate: date });
  }, [updateState]);

  const handleViewChange = useCallback((view: string) => {
    const calendarApi = calendarRef.current?.getApi();
    if (calendarApi) {
      calendarApi.changeView(view);
      updateState({ currentView: view });
    }
  }, [updateState]);

  const handleZoomChange = useCallback((zoom: number) => {
    const baseHeight = 50;
    const slotHeight = Math.max(30, Math.floor((zoom / 100) * baseHeight));
    const eventHeight = Math.max(20, Math.floor(slotHeight * 0.8));
    const fontSize = zoom < 40 ? 9 : zoom < 60 ? 11 : 12;
    const eventSpacing = Math.max(1, Math.floor(zoom / 30));

    if (calendarRef.current?.getApi()) {
      const calendarApi = calendarRef.current.getApi();
      const calendarEl = calendarApi.el;

      if (calendarEl) {
        calendarEl.style.setProperty('--fc-slot-height', `${slotHeight}px`);
        calendarEl.style.setProperty('--fc-daygrid-event-height', `${eventHeight}px`);
        calendarEl.style.setProperty('--event-font-size', `${fontSize}px`);
        calendarEl.style.setProperty('--event-spacing', `${eventSpacing}px`);

        calendarApi.updateSize();
      }
    }

    updateState({ zoomLevel: zoom });
  }, [updateState]);

  const handleNavigate = useCallback((direction: 'prev' | 'next') => {
    const calendarApi = calendarRef.current?.getApi();
    if (calendarApi) {
      if (direction === 'prev') {
        calendarApi.prev();
      } else {
        calendarApi.next();
      }
      const currentDate = calendarApi.getDate();
      updateState({ currentDate: currentDate });
    }
  }, [updateState]);

  const handleDatesSet = useCallback((arg: DatesSetArg) => {
    const calendarApi = calendarRef.current?.getApi();
    if (calendarApi) {
      const currentDate = calendarApi.getDate();
      updateState({
        currentDate: currentDate,
        currentView: arg.view.type
      });
    }
  }, [updateState]);

  const events = useMemo(() =>
    filteredData.map(appointment => formatEventForCalendar(appointment)),
    [filteredData]
  );


  const showTabs = useMemo(() =>
    tabs.length > 1 || activeTab !== 'list',
    [tabs.length, activeTab]
  );

  useEffect(() => {
    handleZoomChange(state.zoomLevel);
  }, [handleZoomChange, state.zoomLevel]);

  return (
    <Box sx={mainContainerStyles.root(state.isDrawerOpen, DRAWER_WIDTH)}>
      <GlobalStyles styles={CalendarGlobalStyles} />
      <ConditionalComponent isValid={activeTab === 'list'}
        defaultComponent={
          <Stack direction="row" justifyContent="flex-end" spacing={{ xs: 0.5, sm: 1 }}>
            <CustomTooltip title={"Ajouter Un Nouveau rendez-vous"} arrow>
              <AddButton
                onClick={handleTabAdd}
                variant="contained"
                endIcon={<FontAwesome icon={faSquarePlus} width={18} />}
              >
                Nouveau rendez-vous
              </AddButton>
            </CustomTooltip>
          </Stack>
        }
      >
        <ScheduleToolbar
          date={state.currentDate}
          currentView={state.currentView}
          zoom={state.zoomLevel}
          onViewChange={handleViewChange}
          onDateChange={handleDateChange}
          onZoomChange={handleZoomChange}
          onFilters={handleFilterChange}
          onResetFilters={handleResetFilters}
          onDrawerToggle={handleDrawerToggle}
          onNavigate={handleNavigate}
          tableHead={tableHead}
        />
      </ConditionalComponent>


      <CustomTabs
        type={TableType.Appointment}
        tabs={tabs}
        activeTab={activeTab}
        handleTabChange={handleTabChange}
        handleTabClose={handleTabClose}
      />
      <ConditionalComponent isValid={activeTab === 'list'} defaultComponent={
        <AppointmentForm
          key={activeTab}
          appointment={tabs.find(tab => tab.id === activeTab)?.content as IAppointment}
          mode={tabs.find(tab => tab.id === activeTab)?.mode || 'view'}
          onSave={handleSave}
          onClose={(forceClose) => handleCancel(activeTab, forceClose)}
          onEdit={handleEdit}
          updateTabContent={updateTabContent}
          tabId={activeTab}
        />
      }>
        <Box sx={calendarStyles.container}>
          <Box sx={calendarStyles.calendarWrapper}>
            <CalendarHeader
              currentView={state.currentView}
              onViewChange={handleViewChange}
              onAddNew={handleTabAdd}
              currentDate={state.currentDate}
            />

            <Box sx={calendarStyles.content}>
              <FullCalendar
                ref={calendarRef}
                plugins={[timeGridPlugin, dayGridPlugin, interactionPlugin]}
                initialView={state.currentView}
                headerToolbar={false}
                locale={frLocale}
                events={events}
                eventClick={({ event }) => handleView(event.extendedProps.appointment)}
                initialDate={new Date()}
                height="100%"
                handleWindowResize={false}
                stickyHeaderDates={true}

                slotDuration="00:30:00"
                slotLabelInterval="01:00"
                nowIndicator
                firstDay={1}
                allDaySlot={false}
                slotMinTime="08:00:00"
                slotMaxTime="20:00:00"
                scrollTime="08:00:00"
                datesSet={handleDatesSet}
                dayHeaderFormat={{
                  weekday: 'short',
                }}

                slotLabelFormat={{
                  hour: '2-digit',
                  minute: '2-digit',
                  hour12: false
                }}
                eventContent={renderEventContent}
                dayCellClassNames="calendar-day-cell"
                dayHeaderClassNames="calendar-header-cell"
                viewClassNames="calendar-view"
                viewDidMount={() => {
                  handleZoomChange(state.zoomLevel);
                }}
                slotEventOverlap={false}
                eventMaxStack={3}
                eventMinHeight={20}
                eventShortHeight={20}
                eventTimeFormat={{
                  hour: '2-digit',
                  minute: '2-digit',
                  hour12: false
                }}

                views={{
                  timeGridDay: {
                    eventTimeFormat: {
                      hour: '2-digit',
                      minute: '2-digit',
                      hour12: false
                    }
                  },
                  timeGridWeek: {
                    eventTimeFormat: {
                      hour: '2-digit',
                      minute: '2-digit',
                      hour12: false
                    }
                  },
                  dayGridMonth: {
                    eventTimeFormat: {
                      hour: '2-digit',
                      minute: '2-digit',
                      hour12: false
                    },
                    displayEventTime: true,
                    displayEventEnd: false
                  }
                }}
              />
            </Box>
          </Box>


        </Box>
      </ConditionalComponent>

      <CustomDrawer
        open={state.isDrawerOpen}
        onClose={handleDrawerToggle}
        drawerWidth={DRAWER_WIDTH}

      >
        <Box sx={drawerStyles.content}>
          <Typography variant="h5" sx={drawerStyles.title}>
            Liste des rendez-vous
          </Typography>

          <AppointmentTable
            filteredData={filteredData}
            table={table}
            handleView={handleView}
            tableHead={tableHead}
            notFound={notFound}
            filters={filters}
            onFilterChange={handleFilterChange}
            handleEdit={handleEdit}
            handleCancel={() => { }}
          />

        </Box>
      </CustomDrawer>
      <UnsavedChangesDialog
        open={showConfirmDialog}
        onClose={() => setShowConfirmDialog(false)}
        onConfirm={handleConfirmDialogAction}
        onCancel={() => setShowConfirmDialog(false)}
      />
    </Box>
  );
}