import { useState, useMemo, useEffect, useCallback } from "react"
import {
  startOfMonth,
  endOfMonth,
  startOfWeek,
  endOfWeek,
  addDays,
  format,
  subMonths,
  addMonths,
  isSameDay,
  isSameMonth,
  getDay,
  getYear,
} from "date-fns"
import { fr } from "date-fns/locale"

export interface CalendarEvent {
  id: string
  startDate: Date
  endDate: Date
  label: string
  color?: string
  bgColor?: string
}

interface UseCalendarProps {
  initialDate?: Date
  initialEvents?: CalendarEvent[]
  onAddEvent?: () => void
}

export function useCalendar({
  initialDate = new Date(),
  initialEvents = [],
  onAddEvent,
}: UseCalendarProps = {}) {
  const [currentDate, setCurrentDate] = useState(initialDate)
  const [events, setEvents] = useState<CalendarEvent[]>(initialEvents)
  const [zoomLevel, setZoomLevel] = useState(50)
  
  useEffect(() => {
    setEvents(initialEvents)
  }, [initialEvents])

  useEffect(() => {
    setCurrentDate(initialDate)
  }, [initialDate])

  const getEventsForDate = useCallback((date: Date) => {
    return events.filter((event) => date >= event.startDate && date <= event.endDate)
  }, [events])

  const calendarData = useMemo(() => {
    const monthStart = startOfMonth(currentDate)
    const monthEnd = endOfMonth(monthStart)
    const calendarStart = startOfWeek(monthStart, { weekStartsOn: 1 })
    const calendarEnd = endOfWeek(monthEnd, { weekStartsOn: 1 })

    const daysOfWeek = Array.from({ length: 7 }, (_, i) => {
      const day = addDays(calendarStart, i)
      return format(day, "EEEE", { locale: fr })
    })

    const weeks = []
    let days = []
    let day = calendarStart

    while (day <= calendarEnd) {
      for (let i = 0; i < 7; i++) {
        days.push(day)
        day = addDays(day, 1)
      }
      weeks.push(days)
      days = []
    }

    return {
      monthStart,
      monthEnd,
      calendarStart,
      calendarEnd,
      daysOfWeek,
      weeks,
    }
  }, [currentDate])

  const yearCalendarData = useMemo(() => {
    const year = getYear(currentDate)
    const weekdays = Array.from({ length: 7 }, (_, i) => {
      const date = new Date(year, 0, i + 1)
      return format(date, "EEE", { locale: fr })
    })

    const months = Array.from({ length: 12 }, (_, i) => {
      const monthDate = new Date(year, i, 1)
      const monthName = format(monthDate, "MMMM", { locale: fr })
      const daysInMonth = new Date(year, i + 1, 0).getDate()
      const firstDayOfMonth = getDay(startOfMonth(monthDate))
      const prevMonthDays = Array.from({ length: firstDayOfMonth }, (_, index) => {
        const prevMonthDate = new Date(year, i, -firstDayOfMonth + index + 1)
        return {
          date: prevMonthDate,
          day: prevMonthDate.getDate(),
          periods: getEventsForDate(prevMonthDate),
        }
      })

      const currentMonthDays = Array.from({ length: daysInMonth }, (_, d) => {
        const dayDate = new Date(year, i, d + 1)
        return {
          date: dayDate,
          day: d + 1,
          periods: getEventsForDate(dayDate),
        }
      })

      const totalDaysToShow = Math.ceil((firstDayOfMonth + daysInMonth) / 7) * 7
      const nextMonthDaysCount = totalDaysToShow - (firstDayOfMonth + daysInMonth)

      const nextMonthDays = Array.from({ length: nextMonthDaysCount }, (_, index) => {
        const nextMonthDate = new Date(year, i + 1, index + 1)
        return {
          date: nextMonthDate,
          day: nextMonthDate.getDate(),
          periods: getEventsForDate(nextMonthDate),
        }
      })

      const allDays = [...prevMonthDays, ...currentMonthDays, ...nextMonthDays]

      return {
        name: monthName,
        days: allDays,
      }
    })

    return {
      year,
      weekdays,
      months
    }
  }, [currentDate, getEventsForDate])

  const formattedMonth = useMemo(() => {
    return format(currentDate, "MMMM yyyy", { locale: fr })
  }, [currentDate])

  const goToPreviousMonth = () => {
    setCurrentDate((prevDate) => subMonths(prevDate, 1))
  }

  const goToNextMonth = () => {
    setCurrentDate((prevDate) => addMonths(prevDate, 1))
  }

  const goToToday = () => {
    setCurrentDate(new Date())
  }

  const isToday = (date: Date) => {
    return isSameDay(date, new Date())
  }

  const isCurrentMonth = (date: Date) => {
    return isSameMonth(date, calendarData.monthStart)
  }

  const addEvent = (event: Omit<CalendarEvent, "id">) => {
    const newEvent = {
      ...event,
      id: Math.random().toString(36).substring(2, 9),
    }
    setEvents((prev) => [...prev, newEvent])
  }

  const removeEvent = (id: string) => {
    setEvents((prev) => prev.filter((event) => event.id !== id))
  }

  const updateEvent = (id: string, updates: Partial<Omit<CalendarEvent, "id">>) => {
    setEvents((prev) => prev.map((event) => (event.id === id ? { ...event, ...updates } : event)))
  }

  const handleAddEvent = () => {
    if (onAddEvent) {
      onAddEvent()
    }
  }

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

  return {
    currentDate,
    setCurrentDate,
    formattedMonth,
    calendarData,
    yearCalendarData,
    events,
    isToday,
    isCurrentMonth,
    getEventsForDate,
    addEvent,
    removeEvent,
    updateEvent,
    goToPreviousMonth,
    goToNextMonth,
    goToToday,
    handleAddEvent,
    zoomLevel,
    handleZoomChange,
  }
}