"use client"

import type React from "react"

import { useEffect, useRef, useState } from "react"
import { format, addMinutes } from "date-fns"
import { fr } from "date-fns/locale"
import { Table, TableBody, TableCell, TableHead, TableRow, Typography, Box, IconButton } from "@mui/material"
import { styled } from "@mui/material/styles"
import { DndContext, DragOverlay, closestCenter, type DragEndEvent, type DragStartEvent } from "@dnd-kit/core"

import type { Driver, ScheduleData, DriverTimeSlot } from "./types"
import FontAwesome from "@/shared/components/fontawesome"
import { faCar, faEye, faEyeSlash, faUserTie, faXmark } from "@fortawesome/free-solid-svg-icons"
import { faOrcid } from "@fortawesome/free-brands-svg-icons"
import { StyledTableContainer } from "@/shared/theme/css"
import {
  calculateTimeSlotWidth,
  groupOverlappingSlots,
  findSlotIndexInGroup,
  StatusColor,
  isTimeSlotInCell,
} from "./utils/schedule-utils"
import { DriverDetailsPopover } from "./components/driver-details-popover"
import { mainColor } from "@/shared/components/table/styles"
import { TrajetDetailsPopover } from "./components/trajet-details.popover"
import { DriverDraggableTimeSlot } from "./components/draggable-time-slot"
import { DroppableCell } from "./components/droppable-cell"
import { DRIVER_TABLE_COLUMNS, mockScheduleData } from "@/shared/_mock/_driverSchedule"
import { useTableManager, type TableConfig } from "@/hooks/use-table-manager"
import CustomDrawer from "@/shared/components/drawer/custom-drawer"
import TrajetForm from "../../trajet/view/trajet-new-view"
import { TypeTrajet, type ITrajet } from "@/shared/types/trajet"
import { _trajets } from "@/shared/_mock/_trajets"
import { ScheduleToolbar } from "@/shared/components/schedule/schedule-toolbar"
import { TableType, type TimeUnit } from "@/shared/types/common"
import type { Dayjs } from "dayjs"
import { TimeSlotBlock } from "./style"
import { _planningEvents } from "@/shared/_mock/_planningEvents"
import { convertEventsToTimeSlots } from "../../planning/utils/planning-utils"
import type { TimeSlot } from "../../planning/types/planning-types"
import { VehicleTimeSlotBlock } from "../../planning/components/draggable-time-slot"
import { InterventionDetailsPopover } from "../../planning/components/intervention-details-popover"
import CustomTooltip from "@/shared/components/tooltips/tooltip-custom"
import { PLANNING_TABLE_COLUMNS } from "../../planning/constants/planning-constants"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import ConfirmDialog from "@/shared/components/dialog/confirmDialog"
import { AbsenceBlock } from "./components/absence-block"

const driverConfig: TableConfig<Driver> = {
  type: "schedule",
  initialData: mockScheduleData.drivers,
  defaultTableHead: DRIVER_TABLE_COLUMNS,
}

const INTERVAL_MINUTES = 15
const CELL_WIDTH = 30
const SLOT_HEIGHT = 35
const LEFT_COLUMN_WIDTH = 152
const DRAWER_WIDTH = 650
const MIN_INTERVALE = ["00", "15", "30", "45"]

export default function DriverSchedule() {
  const [selectedDate, setSelectedDate] = useState(new Date(2024, 11, 10))
  const [zoomLevel, setZoomLevel] = useState(50)
  const [scheduleData, setScheduleData] = useState<ScheduleData>(mockScheduleData)
  const [activeId, setActiveId] = useState<string | null>(null)
  const headerCellRef = useRef<HTMLTableCellElement>(null)
  const minuteCellRef = useRef<HTMLTableCellElement>(null)
  const [leftColumnWidth, setLeftColumnWidth] = useState(LEFT_COLUMN_WIDTH)
  const [cellWidth, setCellWidth] = useState(CELL_WIDTH)
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
  const [hoveredDriver, setHoveredDriver] = useState<any>(null)
  const [anchorElT, setAnchorElT] = useState<HTMLElement | null>(null)
  const [hoveredSlot, setHoveredSlot] = useState<DriverTimeSlot | TimeSlot | null>(null)
  const [copySlot, setCopySlot] = useState<DriverTimeSlot | null>(null)
  const [isDrawerOpen, setIsDrawerOpen] = useState(false)
  const [selectedTimeSlot, setSelectedTimeSlot] = useState<DriverTimeSlot | null>(null)

  const [currentTableHead, setCurrentTableHead] = useState(DRIVER_TABLE_COLUMNS)
  const [showVehicleEvents, setShowVehicleEvents] = useState(false)
  const [vehicleTimeSlots, setVehicleTimeSlots] = useState<TimeSlot[]>([])
  const [targetDriverId, setTargetDriverId] = useState<string>("")

  const [confirmDialog, setConfirmDialog] = useState<{
    open: boolean
    slot: DriverTimeSlot | null
  }>({
    open: false,
    slot: null,
  })
  const [drawerMode, setDrawerMode] = useState<"view" | "copy">("view")
  const { table, filteredData, filters, tableHead, notFound, handleFilterChange, handleResetFilters, handleSave } =
    useTableManager<Driver>({
      ...driverConfig,
      defaultTableHead: currentTableHead,
    })

  useEffect(() => {
    if (showVehicleEvents) {
      const slots = convertEventsToTimeSlots(_planningEvents)
      setVehicleTimeSlots(slots)
      const combinedColumns = [
        ...DRIVER_TABLE_COLUMNS,
        ...PLANNING_TABLE_COLUMNS.filter(
          (planningCol) => !DRIVER_TABLE_COLUMNS.some((driverCol) => driverCol.id === planningCol.id),
        ),
      ]
      setCurrentTableHead(combinedColumns)
    } else {
      setVehicleTimeSlots([])
      setCurrentTableHead(DRIVER_TABLE_COLUMNS)
    }
  }, [showVehicleEvents])

  const handleCopySlot = (originalSlot: DriverTimeSlot) => {
    setCopySlot(originalSlot)
    setDrawerMode("copy")
    setIsDrawerOpen(true)
  }

  const handleConfirmCopy = () => {
    if (copySlot) {
      const newSlot: DriverTimeSlot = {
        ...copySlot,
        id: (scheduleData.timeSlots.length + 1).toString(),
      }

      setScheduleData((prev) => ({
        ...prev,
        timeSlots: [...prev.timeSlots, newSlot],
      }))
    } 
  }

  const handleConfirmMove = () => {
    if (confirmDialog.slot) {
      setScheduleData((prev) => ({
        ...prev,
        timeSlots: prev.timeSlots.map((ts) =>
          ts.id === confirmDialog.slot!.id ? { ...ts, driverId: targetDriverId } : ts,
        ),
      }))
    }

    setConfirmDialog({ open: false, slot: null })
  }

  const handleCancelMove = () => {
    setConfirmDialog({ open: false, slot: null })
  }

  const handleTimeSlotDoubleClick = (slot: DriverTimeSlot) => {
    if (!confirmDialog.open) {
      setSelectedTimeSlot(slot)
      setDrawerMode("view")
      setIsDrawerOpen(true)
    }
  }

  const handlePopoverOpenT = (event: React.MouseEvent<HTMLElement>, slot: DriverTimeSlot | TimeSlot) => {
    event.stopPropagation()
    setAnchorElT(event.currentTarget)
    setHoveredSlot(slot)
  }

  const handlePopoverCloseT = () => {
    setAnchorElT(null)
    setHoveredSlot(null)
  }

  useEffect(() => {
    if (minuteCellRef.current) {
      const width = minuteCellRef.current.getBoundingClientRect().width
      setCellWidth(width)
    }
  }, [zoomLevel])
  useEffect(() => {
    if (headerCellRef.current) {
      const width = headerCellRef.current.getBoundingClientRect().width
      setLeftColumnWidth(width)
    }
  }, [])

  const handleDateChange = (date: Dayjs | Date, newTimeUnit?: TimeUnit) => {
    setSelectedDate(date instanceof Date ? date : date.toDate())
  }

  const handleZoomChange = (zoom: number) => {
    setZoomLevel(zoom)
  }

  const getHourIntervals = () => {
    const intervals = []
    let currentTime = new Date(selectedDate)
    currentTime.setHours(0, 0, 0)

    for (let i = 0; i < 24; i++) {
      intervals.push({
        hour: format(currentTime, "HH"),
        startCell: i * 4,
        endCell: (i + 1) * 4 - 1,
      })
      currentTime = addMinutes(currentTime, 60)
    }
    return intervals
  }

  const handleDragStart = (event: DragStartEvent) => {
    setActiveId(event.active.id as string)
  }

  const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event

    if (over && active.data.current) {
      const timeSlot = active.data.current as DriverTimeSlot
      const newTargetDriverId = over.id as string

      if (timeSlot.driverId !== newTargetDriverId) {
        setTargetDriverId(newTargetDriverId)
        setConfirmDialog({
          open: true,
          slot: { ...timeSlot, driverId: newTargetDriverId },
        })
      }
    }

    setActiveId(null)
  }
  const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>, driver: any) => {
    if (driver.id !== "1") {
      event.preventDefault()
      event.stopPropagation()
      setAnchorEl(event.currentTarget)
      setHoveredDriver(driver)
    }
  }

  const handlePopoverClose = () => {
    setAnchorEl(null)
    setHoveredDriver(null)
  }

  const activeTimeSlot = activeId
    ? scheduleData.timeSlots.find(
        (slot) =>
          `${slot.driverId}-${slot.startHeure}${slot.startMinute}-${slot.endHeure}${slot.endMinute}` === activeId,
      )
    : null

  const toggleVehicleEvents = () => {
    handleResetFilters()
    setShowVehicleEvents((prev) => !prev)
  }

  const planningEventsButton = (
    <CustomTooltip
      arrow
      title={showVehicleEvents ? "Masquer les événements véhicules" : "Afficher les événements véhicules"}
    >
      <IconButton
        onClick={toggleVehicleEvents}
        sx={{
          bgcolor: showVehicleEvents ? "primary.main" : "white",
          color: showVehicleEvents ? "white" : "primary.main",
          "&:hover": {
            bgcolor: showVehicleEvents ? "primary.dark" : "primary.lighter",
          },
        }}
      >
        <FontAwesome icon={showVehicleEvents ? faEyeSlash : faEye} width={18} />
      </IconButton>
    </CustomTooltip>
  )

  return (
    <>
    <DndContext onDragStart={handleDragStart} onDragEnd={handleDragEnd} collisionDetection={closestCenter}>
      <Box sx={{ width: isDrawerOpen ? `calc(100% - ${DRAWER_WIDTH}px)` : undefined }}>
        <Box sx={{ ml: `${leftColumnWidth}px` }}>
          <ScheduleToolbar
            date={selectedDate}
            onDateChange={handleDateChange}
            onZoomChange={handleZoomChange}
            onResetFilters={handleResetFilters}
            onFilters={handleFilterChange}
            initialColumns={currentTableHead}
            type={TableType.Driver}
            rightAction={planningEventsButton}
          />
        </Box>
        <Box
          sx={{
            mt: 2,
            ml: `${leftColumnWidth}px`,
            py: 1,
            borderTopLeftRadius: 16,
            borderTopRightRadius: 16,
            display: "flex",
            fontWeight: 500,
            justifyContent: "center",
            backgroundColor: "white",
          }}
        >
          {format(selectedDate, "EEEE dd/MM/yyyy", { locale: fr })}
        </Box>
        <StyledTableContainer
          sx={{
            maxHeight: "calc(100vh - 200px)",
          }}
        >
          <Table stickyHeader size="small">
            <TableHead>
              <TableRow>
                <HeaderCell
                  sx={{
                    position: "sticky",
                    zIndex: 3,
                    left: 0,
                    backgroundColor: "primary.lighter",
                    border: "none",
                    width: leftColumnWidth,
                    minWidth: leftColumnWidth,
                  }}
                  rowSpan={2}
                />
                {getHourIntervals().map((interval) => {
                  const currentHour = new Date().getHours()
                  const isCurrentHour = currentHour === Number.parseInt(interval.hour, 10)
                  return (
                    <HeaderCell
                      key={interval.hour}
                      colSpan={4}
                      sx={{
                        position: "sticky",
                        backgroundColor: isCurrentHour ? "mainColor" : "#F5F4FC",
                        top: 0,
                        zIndex: 2,
                        border: "none",
                        ...(isCurrentHour && mainColor),
                      }}
                    >
                      {interval.hour}
                    </HeaderCell>
                  )
                })}
              </TableRow>
              <TableRow>
                {getHourIntervals().map((hour) =>
                  MIN_INTERVALE.map((minute) => (
                    <HeaderCell
                      key={`${hour.hour}:${minute}`}
                      ref={minuteCellRef}
                      sx={{
                        position: "sticky",
                        top: 32,
                        zIndex: 2,
                        fontSize: "0.75rem",
                        paddingInline: (theme) => theme.spacing((4 * zoomLevel) / 100),
                      }}
                    >
                      {minute}
                    </HeaderCell>
                  )),
                )}
              </TableRow>
            </TableHead>
            <TableBody>
              {[scheduleData.drivers[0], ...filteredData.filter((d) => d.id !== "1")].map((driver) => (
                <TableRow
                  key={driver.id}
                  hover
                  sx={{
                    ...(driver.id === "1" && {
                      position: "sticky",
                      top: 64,
                      zIndex: 4,
                      backgroundColor: "background.paper",
                      "&:not(:first-of-type)": {
                        backgroundColor: "background.paper",
                        position: "relative",
                      },
                    }),
                  }}
                >
                  <TableCell
                    sx={{
                      position: "sticky",
                      left: 0,
                      backgroundColor: "background.paper",
                      zIndex: driver.id === "1" ? 3 : 2,
                      ...(driver.id === "1" && {
                        "&::before": {
                          content: '""',
                          position: "absolute",
                          top: 0,
                          left: -1,
                          width: "100%",
                          height: "100%",
                          backgroundColor: "primary.lighter",
                          zIndex: -2,
                        },
                        "&::after": {
                          content: '""',
                          position: "absolute",
                          top: 0,
                          left: 0,
                          right: 0,
                          bottom: 0,
                          backgroundColor: "background.paper",
                          borderTopLeftRadius: 16,
                          zIndex: -1,
                        },
                      }),
                    }}
                    onMouseEnter={(e) => handlePopoverOpen(e, driver)}
                    onMouseLeave={handlePopoverClose}
                  >
                    <Box sx={{ whiteSpace: "nowrap" }} display="flex" alignItems="center">
                      <FontAwesome
                        icon={driver.id === "1" ? faXmark : faUserTie}
                        color="primary.main"
                        width={12}
                        sx={{ mr: 1 }}
                      />
                      <Typography sx={{ fontWeight: 500 }} variant="caption">
                        {driver.name}
                      </Typography>
                    </Box>

                    <ConditionalComponent isValid={!!driver.company}>
                      <Box sx={{ whiteSpace: "nowrap" }} display="flex" alignItems="center">
                        <FontAwesome icon={faCar} color="primary.main" width={12} sx={{ mr: 1 }} />
                        <Typography sx={{ fontWeight: 500 }} variant="caption" display="block">
                          {driver.company}
                        </Typography>
                      </Box>
                    </ConditionalComponent>

                    <ConditionalComponent isValid={!!driver.vehicleId}>
                      <Box sx={{ whiteSpace: "nowrap" }} display="flex" alignItems="center">
                        <FontAwesome icon={faOrcid} color="primary.main" width={12} sx={{ mr: 1 }} />
                        <Typography sx={{ fontWeight: 500 }} variant="caption">
                          {driver.vehicleId}
                        </Typography>
                      </Box>
                    </ConditionalComponent>
                  </TableCell>
                  {getHourIntervals().map((hour) =>
                    MIN_INTERVALE.map((minute) => {
                      const driverSlots = scheduleData.timeSlots.filter((slot) => slot.driverId === driver.id)
                      const vehicleSlots = showVehicleEvents
                        ? vehicleTimeSlots.filter((event) => event.id === driver.id)
                        : []

                        const driverAbsences = scheduleData.absences ? scheduleData.absences.filter((absence) =>
                          absence.driverId === driver.id &&
                          absence.startDate === format(selectedDate, "yyyy-MM-dd")) : []

                        const allSlots = [...driverSlots, ...vehicleSlots, ...driverAbsences]
                        const overlappingGroups = groupOverlappingSlots(allSlots)

                        const slotsInCell = allSlots.filter((slot) => isTimeSlotInCell(slot, hour.hour, minute))

                        const maxGroupHeight = overlappingGroups.reduce((max, group) => Math.max(max, group.length), 0)

                        const cellHeight = maxGroupHeight <= 1 ? "100%" : `${(SLOT_HEIGHT + 2) * maxGroupHeight}px`

                        return (
                          <DroppableCell key={`${hour.hour}:${minute}`} driverId={driver.id} height={cellHeight}>
                            {/* Render time slots */}
                            {slotsInCell.map((slot) => {
                              const indexInGroup = findSlotIndexInGroup(slot, overlappingGroups)

                              if ("vehicle" in slot) {
                                return (
                                  <VehicleTimeSlotBlock
                                    key={slot.id}
                                    slot={slot}
                                    width={calculateTimeSlotWidth(
                                      slot.startHeure,
                                      slot.startMinute,
                                      slot.endHeure,
                                      slot.endMinute,
                                      INTERVAL_MINUTES,
                                      cellWidth,
                                    )}
                                    height={maxGroupHeight <= 1 ? "100%" : `${SLOT_HEIGHT}px`}
                                    top={maxGroupHeight <= 1 ? 0 : indexInGroup * (SLOT_HEIGHT + 2)}
                                    handlePopoverOpenT={handlePopoverOpenT}
                                    handlePopoverCloseT={handlePopoverCloseT}
                                    onDoubleClick={() => void 0}
                                  />
                                )
                              }

                              if ("type" in slot) {
                                return (
                                  <AbsenceBlock
                                    key={slot.id}
                                    absence={slot}
                                    width={calculateTimeSlotWidth(
                                      slot.startHeure,
                                      slot.startMinute,
                                      slot.endHeure,
                                      slot.endMinute,
                                      INTERVAL_MINUTES,
                                      cellWidth,
                                    )}
                                    height={maxGroupHeight <= 1 ? "100%" : `${SLOT_HEIGHT}px`}
                                    top={maxGroupHeight <= 1 ? 0 : indexInGroup * (SLOT_HEIGHT + 2)}
                                  />
                                )
                              }

                              return (
                                <DriverDraggableTimeSlot
                                  key={slot.id}
                                  slot={slot}
                                  width={calculateTimeSlotWidth(
                                    slot.startHeure,
                                    slot.startMinute,
                                    slot.endHeure,
                                    slot.endMinute,
                                    INTERVAL_MINUTES,
                                    cellWidth,
                                  )}
                                  height={maxGroupHeight <= 1 ? "100%" : `${SLOT_HEIGHT}px`}
                                  top={indexInGroup * (SLOT_HEIGHT + 2)}
                                  handlePopoverOpenT={handlePopoverOpenT}
                                  handlePopoverCloseT={handlePopoverCloseT}
                                  onDoubleClick={(e) => {
                                    handleTimeSlotDoubleClick(slot)
                                  }}
                                  onCopySlot={handleCopySlot}
                                />
                              )
                            })}
                          </DroppableCell>
                        )
                      }),
                    )}
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </StyledTableContainer>

          <DragOverlay>
            <ConditionalComponent isValid={!!activeTimeSlot}>
              <TimeSlotBlock>{`${activeTimeSlot?.startHeure}:${activeTimeSlot?.startMinute} - ${activeTimeSlot?.endHeure}:${activeTimeSlot?.endMinute}`}</TimeSlotBlock>
            </ConditionalComponent>
          </DragOverlay>
          <DriverDetailsPopover anchorEl={anchorEl} driver={hoveredDriver} onClose={handlePopoverClose} />

        {hoveredSlot ? (
          <ConditionalComponent
            isValid={"vehicle" in hoveredSlot!}
            defaultComponent={
              <TrajetDetailsPopover
                anchorEl={anchorElT}
                color={hoveredSlot!.driverId === "1" ? StatusColor.PRIMARY : hoveredSlot!.color as StatusColor}
                onClose={handlePopoverCloseT}
                data={{
                  circuit: "Circuit Résidentiel Nord",
                  trajet: "Trajet 001 - Matin",
                  schedule: "Lundi à Vendredi (09h00 à 17h00)",
                  wheelchairCount: 5,
                }}
              />
            }
          >
            <InterventionDetailsPopover
              anchorEl={anchorElT}
              onClose={handlePopoverCloseT}
              slot={hoveredSlot}
            />
          </ConditionalComponent>
          ) : null}
        </Box>
        <CustomDrawer
          drawerWidth={DRAWER_WIDTH}
          open={isDrawerOpen}
          onClose={() => {
            setIsDrawerOpen(false)
            setDrawerMode("view")
          }}
        >
          <TrajetForm
            isDrawerElement
            trajet={drawerMode === "copy" ? {
              ...(selectedTimeSlot?.trajet || _trajets[0]) as ITrajet,
              typeTrajet: TypeTrajet.personnalise,
              datePersonnalisation: new Date().toISOString(),
            } : (selectedTimeSlot?.trajet || _trajets[0]) as ITrajet}
            mode={drawerMode}
            onClose={() => setIsDrawerOpen(false)}
            onSave={(trajet) => handleConfirmCopy()}
            tableHead={tableHead}
          />
        </CustomDrawer>
      </DndContext>

      <ConfirmDialog
        open={confirmDialog.open}
        title="Confirmer le déplacement du créneau"
        content={`Voulez-vous vraiment déplacer le trajet du ${confirmDialog.slot?.date} ${confirmDialog.slot?.startHeure}h${confirmDialog.slot?.startMinute} à ${confirmDialog.slot?.endHeure}h${confirmDialog.slot?.endMinute} vers un autre chauffeur ?`}
        onConfirm={handleConfirmMove}
        onCancel={handleCancelMove}
        confirmButtonText="Déplacer"
        confirmButtonColor="primary"
      />
    </>
  )
}

const HeaderCell = styled(TableCell)(({ theme }) => ({
  fontWeight: 500,
  padding: theme.spacing(0.5),
  textAlign: "center",
  borderBlock: `1px solid ${theme.palette.divider}`,
  borderLeft: `1px solid ${theme.palette.divider}`,
  height: 32,
}))
