"use client"

import { useEffect, useState, useMemo } from "react"
import { Typography, Grid, IconButton, Button } from "@mui/material"
import FontAwesome from "../../../../../components/fontawesome/fontawesome"
import { faClock, faCopy, faPlus, faRotateRight, faTimes } from "@fortawesome/free-solid-svg-icons"
import { alpha, Box } from "@mui/system"
import { StyledTimePicker } from "@/shared/theme/css"
import CustomTooltip from "@/shared/components/tooltips/tooltip-custom"
import { LocalizationProvider } from "@mui/x-date-pickers"
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"
import dayjs from "dayjs"
import "dayjs/locale/fr"
import { DAYS } from "@/shared/_mock/_usagers"
import type { TimeValue } from "@/shared/types/usager"
import { MOCKED_SCHEDULE_DATA } from "@/shared/_mock/_avenants"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import type { ScheduleDTO } from "@/shared/types/amendment"
import ActionButtons from "@/shared/components/form/buttons-action"
import type { ModeType } from "@/shared/types/common"
import { useFormikContext } from "formik"
import type { FormikAmendmentPassengerDetails, HorairesSpecifiqueTabsProps, WeeklyScheduleType, WeekScheduleProps } from "./types/formik-types"
import { deepCloneSchedules, mapSchedulesToWeeklySchedule } from "./utils/converters"

dayjs.locale("fr")

const CustomTimeIcon = () => <FontAwesome icon={faClock} sx={{ color: "primary.main" }} />

function WeekSchedule({
  type,
  values,
  onChange,
  onAddField,
  onRemoveField,
  onCopy,
  onReset,
  isReadOnly,
}: WeekScheduleProps) {
  return (
    <Grid spacing={6} sx={{ mx: "5%", mt: 4 }}>
      <Box sx={{ display: "flex", gap: 1 }}>
        <Typography
          variant="h5"
          sx={{
            color: "primary.main",
            fontWeight: (theme) => theme.typography.fontWeightBold,
          }}
        >
          {`Semaine ${type === "pair" ? "paire" : "impaire"}`}
        </Typography>
        <CustomTooltip title="Dupliquer la semaine" arrow>
          <span>
            <IconButton onClick={onCopy} size="small" disabled={isReadOnly}>
              <FontAwesome color={"primary.main"} icon={faCopy} width={18} />
            </IconButton>
          </span>
        </CustomTooltip>
      </Box>

      <Grid container spacing={"5%"}>
        {(["morning", "evening"] as const).map((period) => (
          <Grid item xs={12} md={6} key={period}>
            <Box sx={{ mb: 2, display: "flex", alignItems: "center", gap: 1 }}>
              <Typography variant="h6" color={(theme) => alpha(theme.palette.text.secondary, 0.8)}>
                {period === "morning" ? "Matin" : "Soir"}
              </Typography>
              <CustomTooltip title={`Réinitialiser le ${period === "morning" ? "matin" : "soir"}`} arrow>
                <span>
                  <IconButton onClick={() => onReset(period)} size="small" disabled={isReadOnly}>
                    <FontAwesome
                      color={(theme) => alpha(theme.palette.text.secondary, 0.8)}
                      icon={faRotateRight}
                      width={18}
                    />
                  </IconButton>
                </span>
              </CustomTooltip>
            </Box>
            {DAYS.map((day) => {
              const dayKey = day.toLowerCase()
              const periodData = values[dayKey]?.[period]

              return (
                <Box key={`${dayKey}-${period}`} sx={{ mb: !periodData?.retour && period === "morning" ? "3.1px" : 4 }}>
                  <ConditionalComponent
                    isValid={period === "morning"}
                    defaultComponent={
                      <Box sx={{ display: periodData?.aller ? "flex" : "block", gap: 1, width: "100%" }}>
                        <ConditionalComponent isValid={!!periodData?.aller}>
                          <LocalizationProvider dateAdapter={AdapterDayjs}>
                            <StyledTimePicker
                              label={day + " (Aller)"}
                              value={periodData?.aller}
                              onChange={(v) => onChange(dayKey, period, "aller", v)}
                              readOnly={isReadOnly}
                              slots={{ openPickerIcon: CustomTimeIcon }}
                              slotProps={{
                                textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                              }}
                              views={["hours", "minutes"]}
                              format="HH:mm"
                            />
                          </LocalizationProvider>
                        </ConditionalComponent>

                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                          <StyledTimePicker
                            label={day + " (Retour)"}
                            value={periodData?.retour || null}
                            onChange={(v) => onChange(dayKey, period, "retour", v)}
                            readOnly={isReadOnly}
                            slots={{ openPickerIcon: CustomTimeIcon }}
                            slotProps={{
                              textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                            }}
                            views={["hours", "minutes"]}
                            format="HH:mm"
                          />
                        </LocalizationProvider>
                      </Box>
                    }
                  >
                    <Box sx={{ display: periodData?.retour ? "flex" : "block", gap: 1, width: "100%" }}>
                      <Box sx={{ flex: 1 }}>
                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                          <StyledTimePicker
                            label={day + " (Aller)"}
                            value={periodData?.aller || null}
                            onChange={(v) => onChange(dayKey, period, "aller", v)}
                            readOnly={isReadOnly}
                            slots={{ openPickerIcon: CustomTimeIcon }}
                            slotProps={{
                              textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                            }}
                            views={["hours", "minutes"]}
                            format="HH:mm"
                          />
                        </LocalizationProvider>
                        <ConditionalComponent isValid={!periodData?.retour}>
                          <Button
                            disabled={isReadOnly}
                            startIcon={<FontAwesome width={14} icon={faPlus} />}
                            onClick={(e) => {
                              e.preventDefault()
                              e.stopPropagation()
                              onAddField(dayKey, period, "retour")
                            }}
                            sx={{ color: (theme) => theme.palette.primary.main, fontSize: "12px" }}
                            size="small"
                          >
                            Ajouter retour
                          </Button>
                        </ConditionalComponent>
                      </Box>

                      <ConditionalComponent isValid={!!periodData?.retour}>
                        <Box sx={{ display: "flex", gap: 1, flex: 1, alignItems: "center" }}>
                          <LocalizationProvider dateAdapter={AdapterDayjs}>
                            <StyledTimePicker
                              label={day + " (Retour)"}
                              value={periodData?.retour}
                              onChange={(v) => onChange(dayKey, period, "retour", v)}
                              readOnly={isReadOnly}
                              slots={{ openPickerIcon: CustomTimeIcon }}
                              slotProps={{
                                textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                              }}
                              views={["hours", "minutes"]}
                              format="HH:mm"
                            />
                          </LocalizationProvider>
                          <CustomTooltip title="Supprimer le retour" arrow>
                            <span>
                              <IconButton
                                onClick={(e) => {
                                  e.preventDefault()
                                  e.stopPropagation()
                                  onRemoveField(dayKey, period, "retour")
                                }}
                                disabled={isReadOnly}
                                sx={{ color: (theme) => theme.palette.error.main, p: 0 }}
                              >
                                <FontAwesome icon={faTimes} />
                              </IconButton>
                            </span>
                          </CustomTooltip>
                        </Box>
                      </ConditionalComponent>
                    </Box>
                  </ConditionalComponent>
                </Box>
              )
            })}
          </Grid>
        ))}
      </Grid>
    </Grid>
  )
}

function useFormikContextSafe() {
  const context = useFormikContext<FormikAmendmentPassengerDetails>()
  return context || null
}

export default function HorairesSpecifiqueTabs({
  mode,
  title,
  withData,
  schedules,
  useFormik = false,
}: HorairesSpecifiqueTabsProps) {
  const isReadOnly = mode === "view"

  const [localSelectedDays, setLocalSelectedDays] = useState<WeeklyScheduleType>({
    pair: {},
    impair: {},
  })

  const formikContext = useFormikContextSafe()

  const shouldUseFormik = useMemo(() => {
    return useFormik && formikContext !== null
  }, [useFormik, formikContext])

  const selectedDays = useMemo(() => {
    if (shouldUseFormik && formikContext) {
      return formikContext.values.weeklySchedules
    }
    return localSelectedDays
  }, [shouldUseFormik, formikContext, localSelectedDays])

  const updateSelectedDays = (newSchedules: WeeklyScheduleType) => {
    if (shouldUseFormik && formikContext) {
      formikContext.setFieldValue("weeklySchedules", newSchedules)
    } else {
      setLocalSelectedDays(newSchedules)
    }
  }

  useEffect(() => {
    if (withData) {
      let initialData: WeeklyScheduleType

      if (schedules) {
        initialData = mapSchedulesToWeeklySchedule(schedules)
      } else if (shouldUseFormik && formikContext) {
        return
      } else {
        initialData = MOCKED_SCHEDULE_DATA
      }

      if (!shouldUseFormik) {
        setLocalSelectedDays(initialData)
      }
    }
  }, [withData, schedules, shouldUseFormik, formikContext])

  const handleChange = (
    weekType: "pair" | "impair",
    day: string,
    period: "morning" | "evening",
    type: "aller" | "retour",
    value: TimeValue,
  ) => {
    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: {
          ...(selectedDays[weekType][day] || { morning: { aller: null }, evening: { retour: null } }),
          [period]: {
            ...(selectedDays[weekType][day]?.[period] || {}),
            [type]: value,
          },
        },
      },
    }

    updateSelectedDays(newSchedules)
  }

  const handleAddField = (
    weekType: "pair" | "impair",
    day: string,
    period: "morning" | "evening",
    field: "aller" | "retour",
  ) => {
    const defaultTime = dayjs().hour(12).minute(0)
    const eveningAllerTime = dayjs().hour(14).minute(0)

    const currentDayData = selectedDays[weekType][day] || {
      morning: { aller: null },
      evening: { retour: null },
    }

    let newDayData = { ...currentDayData }

    newDayData = {
      ...newDayData,
      [period]: {
        ...newDayData[period],
        [field]: defaultTime,
      },
    }

    if (period === "morning" && field === "retour") {
      newDayData = {
        ...newDayData,
        evening: {
          ...newDayData.evening,
          aller: eveningAllerTime,
        },
      }
    }

    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: newDayData,
      },
    }

    updateSelectedDays(newSchedules)
  }

  const handleCopy = (fromType: "pair" | "impair") => {

    const newSchedules = {
      ...selectedDays,
      [fromType === "pair" ? "impair" : "pair"]: deepCloneSchedules(selectedDays[fromType]),
    }

    updateSelectedDays(newSchedules)
  }

  const handleReset = (weekType: "pair" | "impair", period: "morning" | "evening") => {
    const updatedDays = Object.entries(selectedDays[weekType]).reduce(
      (acc, [day, data]) => ({
        ...acc,
        [day]: {
          ...data,
          [period]: period === "morning" ? { aller: null, retour: null } : { aller: null, retour: null },
        },
      }),
      {},
    )

    const newSchedules = {
      ...selectedDays,
      [weekType]: updatedDays,
    }

    updateSelectedDays(newSchedules)
  }

  const handleRemoveField = (
    weekType: "pair" | "impair",
    day: string,
    period: "morning" | "evening",
    field: "aller" | "retour",
  ) => {
    const currentDayData = selectedDays[weekType][day] || {
      morning: { aller: null },
      evening: { retour: null },
    }

    let newDayData = { ...currentDayData }

    newDayData = {
      ...newDayData,
      [period]: {
        ...newDayData[period],
        [field]: null,
      },
    }

    if (period === "morning" && field === "retour") {
      newDayData = {
        ...newDayData,
        evening: {
          ...newDayData.evening,
          aller: null,
        },
      }
    }

    if (period === "evening" && field === "aller") {
      newDayData = {
        ...newDayData,
        morning: {
          ...newDayData.morning,
          retour: null,
        },
      }
    }

    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: newDayData,
      },
    }

    updateSelectedDays(newSchedules)
  }

  return (
    <Box>
      <Typography
        variant="h5"
        sx={{
          color: "primary.main",
          fontWeight: "bold",
          mb: 4,
        }}
      >
        {title}
      </Typography>
      <WeekSchedule
        type="pair"
        values={selectedDays.pair}
        onChange={(day, period, type, value) => handleChange("pair", day, period, type, value)}
        onAddField={(day, period, field) => handleAddField("pair", day, period, field)}
        onRemoveField={(day, period, field) => handleRemoveField("pair", day, period, field)}
        onCopy={() => handleCopy("pair")}
        onReset={(period) => handleReset("pair", period)}
        isReadOnly={isReadOnly}
      />

      <WeekSchedule
        type="impair"
        values={selectedDays.impair}
        onChange={(day, period, type, value) => handleChange("impair", day, period, type, value)}
        onAddField={(day, period, field) => handleAddField("impair", day, period, field)}
        onRemoveField={(day, period, field) => handleRemoveField("impair", day, period, field)}
        onCopy={() => handleCopy("impair")}
        onReset={(period) => handleReset("impair", period)}
        isReadOnly={isReadOnly}
      />
      <ConditionalComponent isValid={!isReadOnly && !!schedules}>
        <Grid item xs={12}>
          <ActionButtons onSave={() => void 0} onCancel={() => void 0} mode={mode} />
        </Grid>
      </ConditionalComponent>
    </Box>
  )
}
