"use client"

import { useState, useEffect } from "react"
import { Box, Checkbox, Stack, Theme, Typography } from "@mui/material"
import { styled } from "@mui/material/styles"
import { DaysOfWeek, WeekType } from "@/shared/types/passenger"
import ConditionalComponent from "../table/ConditionalComponent"
import CustomTooltip from "../tooltips/tooltip-custom"
import { PeriodOfDay } from "@/shared/types/ammendment-passenger"
import { DaySchedule, WeekSchedule } from "./etablissement-jours-field"
import { DayCheckbox, DayLabel } from "./style"

interface TransportScheduleFieldProps {
  initialSchedules?: WeekSchedule[]
  otherSchedules?: WeekSchedule[][]
  onChange: (schedules: WeekSchedule[]) => void
  isReadOnly: boolean
}

export const DAYS_CONFIG = [
  { key: DaysOfWeek.MONDAY, label: "L", fullName: "Lundi" },
  { key: DaysOfWeek.TUESDAY, label: "M", fullName: "Mardi" },
  { key: DaysOfWeek.WEDNESDAY, label: "M", fullName: "Mercredi" },
  { key: DaysOfWeek.THURSDAY, label: "J", fullName: "Jeudi" },
  { key: DaysOfWeek.FRIDAY, label: "V", fullName: "Vendredi" },
  { key: DaysOfWeek.SATURDAY, label: "S", fullName: "Samedi" },
  { key: DaysOfWeek.SUNDAY, label: "D", fullName: "Dimanche" },
]

export const PERIODS_CONFIG = [
  { key: PeriodOfDay.MORNING, label: "M", fullName: "Matin" },
  { key: PeriodOfDay.EVENING, label: "S", fullName: "Soir" },
]

export const WEEK_TYPES = [
  { key: WeekType.EVEN, label: "Paire", fullName: "Semaine Paire" },
  { key: WeekType.ODD, label: "Impaire", fullName: "Semaine Impaire" },
]

export default function TransportScheduleField({
  initialSchedules = [],
  otherSchedules = [],
  onChange,
  isReadOnly,
}: TransportScheduleFieldProps) {
  const [schedules, setSchedules] = useState<WeekSchedule[]>(initialSchedules)

  useEffect(() => {
    setSchedules(initialSchedules)
  }, [initialSchedules])

  const isPeriodSelectedInOtherSchedules = (
    weekType: WeekType,
    dayOfWeek: DaysOfWeek,
    periodOfDay: PeriodOfDay,
  ): boolean => {
    if (!otherSchedules || !Array.isArray(otherSchedules) || otherSchedules.length === 0) {
      return false
    }

    return otherSchedules.some((otherScheduleList) => {
      if (!otherScheduleList || !Array.isArray(otherScheduleList)) {
        return false
      }

      return otherScheduleList.some((daySchedule) => {
        if (!daySchedule || !daySchedule.schedules || !Array.isArray(daySchedule.schedules)) {
          return false
        }

        return (
          daySchedule.weekType === weekType &&
          daySchedule.schedules.some((schedule) => {
            if (!schedule) {
              return false
            }
            return schedule.dayOfWeek === dayOfWeek && schedule.periodOfDay === periodOfDay
          })
        )
      })
    })
  }

  const isPeriodSelected = (weekType: WeekType, dayOfWeek: DaysOfWeek, periodOfDay: PeriodOfDay): boolean => {
    if (!schedules || !Array.isArray(schedules)) {
      return false
    }

    return schedules.some((daySchedule) => {
      if (!daySchedule || !daySchedule.schedules || !Array.isArray(daySchedule.schedules)) {
        return false
      }

      return (
        daySchedule.weekType === weekType &&
        daySchedule.schedules.some((schedule) => {
          if (!schedule) {
            return false
          }
          return schedule.dayOfWeek === dayOfWeek && schedule.periodOfDay === periodOfDay
        })
      )
    })
  }

  const handlePeriodChange = (weekType: WeekType, dayOfWeek: DaysOfWeek, periodOfDay: PeriodOfDay) => {
    const isCurrentlySelected = isPeriodSelected(weekType, dayOfWeek, periodOfDay)
    const isSelectedInOther = isPeriodSelectedInOtherSchedules(weekType, dayOfWeek, periodOfDay)

    if (!isCurrentlySelected && isSelectedInOther) {
      return
    }

    let newSchedules = [...schedules]

    if (isCurrentlySelected) {
      newSchedules = newSchedules.map((daySchedule) => {
        if (daySchedule.weekType === weekType) {
          return {
            ...daySchedule,
            schedules: daySchedule.schedules.filter(
              (schedule) => !(schedule.dayOfWeek === dayOfWeek && schedule.periodOfDay === periodOfDay),
            ),
          }
        }
        return daySchedule
      })

      newSchedules = newSchedules.filter((daySchedule) => daySchedule.schedules.length > 0)
    } else {
      const existingDaySchedule = newSchedules.find((ds) => ds.weekType === weekType)

      if (existingDaySchedule) {
        existingDaySchedule.schedules.push({ id: "", dayOfWeek, periodOfDay })
      } else {
        newSchedules.push({
          id: "",
          weekType,
          schedules: [{ id: "", dayOfWeek, periodOfDay }],
        })
      }
    }

    setSchedules(newSchedules)
    onChange(newSchedules)
  }

  const handleSelectAllWeek = (weekType: WeekType, checked: boolean) => {
    let newSchedules = [...schedules]

    if (checked) {
      const schedulesToAdd: DaySchedule[] = []

      DAYS_CONFIG.forEach((day) => {
        PERIODS_CONFIG.forEach((period) => {
          if (!isPeriodSelectedInOtherSchedules(weekType, day.key, period.key)) {
            schedulesToAdd.push({
              id: "",
              dayOfWeek: day.key,
              periodOfDay: period.key,
            })
          }
        })
      })

      if (schedulesToAdd.length > 0) {
        const existingDaySchedule = newSchedules.find((ds) => ds.weekType === weekType)

        if (existingDaySchedule) {
          existingDaySchedule.schedules = schedulesToAdd
        } else {
          newSchedules.push({
            id: "",
            weekType,
            schedules: schedulesToAdd,
          })
        }
      }
    } else {
      newSchedules = newSchedules.filter((daySchedule) => daySchedule.weekType !== weekType)
    }

    setSchedules(newSchedules)
    onChange(newSchedules)
  }

  const isAllWeekSelected = (weekType: WeekType): boolean => {
    const availableSlots = DAYS_CONFIG.reduce((count, day) => {
      return (
        count +
        PERIODS_CONFIG.reduce((periodCount, period) => {
          return periodCount + (isPeriodSelectedInOtherSchedules(weekType, day.key, period.key) ? 0 : 1)
        }, 0)
      )
    }, 0)

    const selectedSlots = schedules
      .filter((ds) => ds && ds.weekType === weekType)
      .reduce((count, ds) => count + (ds.schedules ? ds.schedules.length : 0), 0)

    return availableSlots > 0 && selectedSlots === availableSlots
  }

  const canSelectAllWeek = (weekType: WeekType): boolean => {
    return DAYS_CONFIG.some((day) =>
      PERIODS_CONFIG.some((period) => !isPeriodSelectedInOtherSchedules(weekType, day.key, period.key)),
    )
  }

  const renderDayPeriod = (weekType: WeekType, dayOfWeek: DaysOfWeek) => {
    const dayConfig = DAYS_CONFIG.find((d) => d.key === dayOfWeek)
    if (!dayConfig) return null

    return (
      <Stack direction="row" spacing={0.3} alignItems="center">
        {PERIODS_CONFIG.map((period) => {
          const isSelected = isPeriodSelected(weekType, dayOfWeek, period.key)
          const isDisabledByOther = isPeriodSelectedInOtherSchedules(weekType, dayOfWeek, period.key)
          const isDisabled = isReadOnly || (!isSelected && isDisabledByOther)

          const checkbox = (
            <Box sx={{ position: "relative" }}>
              <DayCheckbox
                disabled={isDisabled}
                checked={isSelected}
                onChange={() => handlePeriodChange(weekType, dayOfWeek, period.key)}
                size="small"
              />
              <DayLabel
                sx={{
                  color: isSelected ? (theme: Theme) => theme.palette.primary.contrastText : "inherit",
                }}
              >
                {`${dayConfig.label}${period.label}`}
              </DayLabel>
            </Box>
          )

          return (
            <ConditionalComponent
              key={period.key}
              isValid={isDisabledByOther && !isReadOnly}
              defaultComponent={checkbox}
            >
              <CustomTooltip
                arrow
                colorSchema="warning"
                title="Cette période est déjà sélectionnée dans un autre établissement"
              >
                {checkbox}
              </CustomTooltip>
            </ConditionalComponent>
          )
        })}
      </Stack>
    )
  }

  return (
    <Stack spacing={1.5}>
      {WEEK_TYPES.map((weekType) => (
        <Box key={weekType.key}>
          <Stack direction="row" alignItems="center" spacing={1}>
            <Stack direction="row" alignItems="center" spacing={0.5}>
              <ConditionalComponent
                isValid={!(canSelectAllWeek(weekType.key) || isReadOnly)}
                defaultComponent={
                  <Checkbox
                    sx={{ p: 0 }}
                    disabled={isReadOnly}
                    checked={isAllWeekSelected(weekType.key)}
                    onChange={(e) => handleSelectAllWeek(weekType.key, e.target.checked)}
                    size="small"
                  />
                }
              >
                <CustomTooltip
                  arrow
                  colorSchema="warning"
                  title="Certaines périodes sont déjà sélectionnées dans d'autres établissements"
                >
                  <span>
                    <Checkbox sx={{ p: 0 }} disabled={true} checked={isAllWeekSelected(weekType.key)} size="small" />
                  </span>
                </CustomTooltip>
              </ConditionalComponent>
              <Typography sx={{ fontSize: "10px", minWidth: 40, textAlign: "left" }}>{weekType.label}</Typography>
            </Stack>
            <Stack direction="row" spacing={1} justifyContent="space-between" flexGrow={1}>
              {DAYS_CONFIG.map((day) => (
                <Box key={`${weekType.key}-${day.key}`}>{renderDayPeriod(weekType.key, day.key)}</Box>
              ))}
            </Stack>
          </Stack>
        </Box>
      ))}
    </Stack>
  )
}