"use client"

import FullCalendar from "@fullcalendar/react"
import dayGridPlugin from "@fullcalendar/daygrid"
import listPlugin from "@fullcalendar/list"
import moment from "moment"
import classNames from "classnames"
import interactionPlugin from "@fullcalendar/interaction"
import { Dispatch, SetStateAction, forwardRef, useImperativeHandle, useMemo, useRef, useState } from "react"
import { useRouter } from "@/i18n/routing"
import { useTranslations } from "next-intl"
import { Collapse, Drawer } from "antd"
import { useRecoilState, useRecoilValue } from "recoil"
import { eventState, viewCalendarState } from "@/recoil"
import { find, isEmpty } from "lodash"

import { CalendarCss, DrawerCss } from "./style"
import { TYPE_CALENDAR } from "@/config/constant"
import { ICalendarEventQueryType, ICalendarEventRes, IFormatTitleEvent } from "@/type/Calendar"
import { ScheduleItem } from "./ScheduleItem"
import { useGetEventTypes } from "@/hook/useCalendar"
import { useSearchParams } from "next/navigation"
import dayjs from "dayjs"

type IProps = {
  dataEvents?: {
    data: {
      total_pages: number
      next_page_num: number
      events: ICalendarEventRes[]
    }
  }
  formatStartEnd: (date: any, type: "startOf" | "endOf", value?: string) => string
  setQuery: Dispatch<SetStateAction<ICalendarEventQueryType>>
  query: ICalendarEventQueryType
  confirmDelete: (id: number) => void
}

export const Calendar = forwardRef(({ dataEvents, formatStartEnd, setQuery, query, confirmDelete }: IProps, ref) => {
  const router = useRouter()
  const calendarRef = useRef<FullCalendar | null>(null)
  const viewCalendar = useRecoilValue(viewCalendarState)
  const searchParams = useSearchParams()

  const trans = useTranslations("calendar")

  const [eventArr, setEventArr] = useRecoilState(eventState)
  const [dateClick, setDateClick] = useState<IFormatTitleEvent>({})

  const { data: dataType, isLoading } = useGetEventTypes()

  const cusTomEvent = useMemo(() => {
    const allEvent = dataEvents?.data?.events?.map((e) => {
      const start = formatStartEnd(Number(e?.date), "startOf", e?.time_from)
      const end = formatStartEnd(Number(e?.todate), "endOf", e?.time_to)
      const color = find(TYPE_CALENDAR, { type: e?.type })?.color || "#111827"
      const eV = {
        title: e?.title || "",
        description: e?.description || "",
        type: e?.type,
        id: e?.id,
        start,
        end,
        color,
      }

      return eV
    })

    return allEvent
  }, [dataEvents?.data])

  const [open, setOpen] = useState<boolean>(false)
  const [loading, setLoading] = useState<boolean>(true)

  const showLoading = () => {
    setOpen(true)
    setLoading(true)

    // Simple loading mock. You should add cleanup logic in real world.
    setTimeout(() => {
      setLoading(false)
    }, 1500)
  }

  const handleSelectDate = (values: any) => {
    setDateClick({ YYYY: moment(values?.start).format("YYYY"), Do: moment(values?.start).format("Do"), MM: moment(values?.start).format("MMMM") })
  }

  const handleEventOrDateClick = (date: Date) => {
    const eventsForDate = (cusTomEvent || [])?.filter((event) => {
      const eventStart = new Date(event.start)
      const eventEnd = event.end ? new Date(event.end) : eventStart
      eventStart.setHours(0, 0, 0, 0)
      eventEnd.setHours(23, 59, 59, 999)

      return date >= eventStart && date <= eventEnd
    })
    setEventArr(eventsForDate)
  }

  const handleSelectEvent = (info: any) => {
    const selectedDate = new Date(info?.event?.startStr)
    handleEventOrDateClick(selectedDate)
    showLoading()
  }

  const handleDateClick = (info: any) => {
    const selectedDate = new Date(info?.dateStr)
    handleEventOrDateClick(selectedDate)
    showLoading()
  }

  const renderDayHeaderContent = (dateInfo: any) => {
    const month = moment(dateInfo.date).format("MMMM")
    const day = moment(dateInfo.date).format("Do")
    const year = moment(dateInfo.date).format("YYYY")

    return (
      <>
        <Collapse
          expandIconPosition="end"
          items={[
            {
              label: (
                <div
                  onClick={() => handleEventOrDateClick(dateInfo.date)}
                  className="flex items-center text-base md:text-[30px] md:leading-[38px] font-medium text-[var(--secondary-100)]">
                  <span className="text-black">{month}</span>
                  <span className="text-[var(--primary--70)] mx-2">{day}</span>
                  <span className="text-black">{year}</span>
                </div>
              ),
              children: (
                <div>
                  {!isEmpty(eventArr)
                    ? eventArr?.map((item) => (
                        <ScheduleItem
                          key={item?.id}
                          id={item?.id}
                          type={find(dataType?.data, { id: item?.type })?.name || ""}
                          title={item.title}
                          description={item.description}
                          color={item.color}
                          start={item?.start}
                          end={item?.end}
                          confirmDelete={confirmDelete}
                        />
                      ))
                    : null}
                </div>
              ),
            },
          ]}
        />
      </>
    )
  }

  useImperativeHandle(ref, () => ({
    _onGotoDate(date: string) {
      if (calendarRef?.current) {
        const calendarApi = calendarRef?.current?.getApi()
        calendarApi.gotoDate(date)
      }
    },
  }))

  const handleClickPreNextBtn = (type: "next" | "prev") => {
    if (calendarRef?.current) {
      const calendarApi = calendarRef?.current?.getApi()
      type === "next" ? calendarApi.next() : calendarApi.prev()
      if (!searchParams.has("searchTitle")) {
        const currentMonth = calendarApi.getDate().getMonth()
        const currentYear = calendarApi.getDate().getFullYear()
        if (currentYear && currentYear) {
          const startOfMonth = dayjs(new Date(currentYear, currentMonth, 1)).startOf("day")
          const endOfMonth = startOfMonth.endOf("month")

          setQuery({
            startDate: startOfMonth.unix(),
            endDate: endOfMonth.unix(),
          })
        }
      }
    }
  }

  return (
    <>
      <div className="grow overflow-y-auto overflow-x-hidden">
        <div className={classNames(`pb-4 pt-5 px-4 md:px-5 h-full`, CalendarCss)}>
          <FullCalendar
            ref={calendarRef}
            // key={viewCalendar}
            key={`${viewCalendar}-${Object.values(query).join("-")}`}
            plugins={[interactionPlugin, listPlugin, dayGridPlugin]}
            initialView={viewCalendar}
            customButtons={{
              addEvent: {
                text: `+ Add Event`,
                click: () => {
                  router.push("calendar/add-event")
                },
              },
              customPrev: {
                text: `<`,
                click: () => {
                  handleClickPreNextBtn("prev")
                },
              },
              customNext: {
                text: `>`,
                click: () => {
                  handleClickPreNextBtn("next")
                },
              },
            }}
            headerToolbar={{
              start: "customPrev title customNext",
              end: "addEvent",
            }}
            titleFormat={(date) => {
              return moment(date?.date).format("MMMM, YYYY")
            }}
            timeZone={Intl.DateTimeFormat().resolvedOptions().timeZone}
            eventClick={handleSelectEvent}
            dateClick={handleDateClick}
            selectable
            select={handleSelectDate}
            events={cusTomEvent}
            dayHeaderContent={viewCalendar === "listMonth" ? renderDayHeaderContent : undefined}
          />
        </div>
      </div>
      <Drawer
        className={classNames(``, DrawerCss)}
        closable
        destroyOnClose
        title={<p>{trans("calendar")}</p>}
        placement="right"
        open={open}
        loading={loading || isLoading}
        onClose={() => setOpen(false)}
        width={594}>
        <h2 className="text-5xl leading-[60px] font-medium mb-10">
          {dateClick?.MM || ""} <span className="text-yellow-500">{dateClick?.Do || ""}</span> {dateClick?.YYYY || ""}
        </h2>
        {!isEmpty(eventArr)
          ? eventArr?.map((item) => (
              <ScheduleItem
                key={item?.id}
                id={item?.id}
                type={find(dataType?.data, { id: item?.type })?.name || ""}
                title={item.title}
                description={item.description}
                color={item.color}
                start={item?.start}
                end={item?.end}
                confirmDelete={confirmDelete}
              />
            ))
          : null}
      </Drawer>
    </>
  )
})
