"use client";

import { ApiResponse, request } from "@/hooks/use-api";
import "@schedule-x/theme-shadcn/dist/index.css";
import { useNextCalendarApp, ScheduleXCalendar } from "@schedule-x/react";
import { createEventsServicePlugin } from "@schedule-x/events-service";
import { createDragAndDropPlugin } from "@schedule-x/drag-and-drop";
import { createResizePlugin } from "@schedule-x/resize";
import { createEventRecurrencePlugin } from "@schedule-x/event-recurrence";
import {
	createViewDay,
	createViewWeek,
} from "@schedule-x/calendar";
import { useEffect, useState } from "react";
import { format } from "date-fns";
import { Dialog, DialogProps } from "@radix-ui/react-dialog";
import {
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { KeyedMutator } from "swr";
import { getCookie } from "cookies-next";
import { useTheme } from "next-themes";
import { EventForm, EventFormValues } from "./event-dialog";
import ICalendarEvent from "@/interfaces/ICalendarEvent";

const mapFrequencyToRrule = (frequency: "unique" | "quotidien" | "hebdomadaire" | "mensuel", frequencyEndDate?: Date): string => {
  let rrule = "";

  switch (frequency) {
    case "quotidien":
      rrule = "FREQ=DAILY";
      break;
    case "hebdomadaire":
      rrule = "FREQ=WEEKLY";
      break;
    case "mensuel":
      rrule = "FREQ=MONTHLY";
      break;
    default:
      return "";
  }

  if (frequencyEndDate) {
    const until = frequencyEndDate.getTime();
    const untilDate = new Date(until);
    const epochDateString = untilDate.toISOString().replace(/[-:]/g, "").split(".")[0]; // Format as YYYYMMDDTHHmmss
    rrule += `;UNTIL=${epochDateString}`;
  }

  return rrule;
};

const Planning: React.FC<{
	events: ICalendarEvent[];
	mutate?: KeyedMutator<ApiResponse<ICalendarEvent[]>>;
}> = ({ events, mutate }) => {
	const { resolvedTheme } = useTheme();
	console.log(resolvedTheme);
	const isConnected = getCookie("auth_token");
	const plugins = isConnected
		? [
			createEventsServicePlugin(),
			createDragAndDropPlugin(),
			createResizePlugin(),
			createEventRecurrencePlugin(),
		]
		: [];
	const [eventSelected, setEventSelected] =
		useState<ICalendarEvent | null>(null);
	const [newEvent, setNewEvent] = useState<Omit<
		ICalendarEvent,
		"id"
	> | null>(null);

	const handleEventUpdate = async (eventSelected: ICalendarEvent) => {
		const event: ICalendarEvent = {
			...eventSelected,
			start: `${new Date(eventSelected.start).toISOString()}`,
			end: `${new Date(eventSelected.end).toISOString()}`,
		};
		try {
			const res = await request<undefined>(`/events/${event.id}/update`, {
				method: "PATCH",
				body: event,
				requiresAuth: true,
				csrfToken: false,
			});
			if (res.status === "Error") {
				// calendar?.events?.update(oldEvent);
			}
		} catch (e) {
			console.log(e);
		}
	};

	const calendar = useNextCalendarApp(
		{
			theme: "shadcn",
			views: [createViewDay(), createViewWeek()],
			defaultView: "week",
			isDark: resolvedTheme === "dark" ? true : false,
			isResponsive: true,
			locale: "fr-FR",
			dayBoundaries: {
				start: "06:00",
				end: "00:00",
			},
			events: events.map((event) => ({
				...event,
				start: format(new Date(event.start), "yyyy-MM-dd HH:mm"),
				end: format(new Date(event.end), "yyyy-MM-dd HH:mm"),
			})),
			callbacks: {
				onEventClick(event, e) {	
					setEventSelected(event as ICalendarEvent);
				},	
				async onEventUpdate(newEvent) {
	
					await handleEventUpdate(newEvent as ICalendarEvent);
				},
			},
		},
		plugins,
	);

	useEffect(() => {
		calendar?.events.getAll();
	}, []);

	useEffect(() => {
		calendar?.setTheme(resolvedTheme === "dark" ? "dark" : "light");
	}, [resolvedTheme]);

	const AddButton: React.FC = () => (
		<Button onClick={() => setNewEvent({})} variant="outline">
			Nouveau
		</Button>
	);

	return (
		<div>
			<div className="m-8">
				<AddButton />
				<ScheduleXCalendar calendarApp={calendar} />
			</div>
			{newEvent && (
				<EventDialog
					open={newEvent !== null || false}
					onOpenChange={(open) => {
						setNewEvent((e) => (open ? e : null));
					}}
					event={newEvent}
					onSubmitEvent={async (eventFormValues) => {
						const rrule = mapFrequencyToRrule(
							eventFormValues.frequency,
							eventFormValues.frequencyEndDate
						)
						try {
							const event: Omit<ICalendarEvent, "id"> = {
								...newEvent,
								start: `${eventFormValues.startDate} ${eventFormValues.startTime}`,
								end: `${eventFormValues.endDate} ${eventFormValues.endTime}`,
								title: `${eventFormValues.title}`,
								fullDay: eventFormValues.fullDay,
								rrule: rrule,
								isVisible: eventFormValues.isVisible
							}
							const res = await request<undefined>(
								`/events/new`,
								{
									method: "POST",
									body: event,
									requiresAuth: true,
									csrfToken: false,
								},
							);
							if (res.status === "Error") {
								console.log("Error");
							}
							if (res.status === "Success") {
								mutate?.();
								console.log("Success");
							}
						} catch (e) {
							console.log(e);
						}
					}}
				/>
			)}
			{eventSelected && (
				<EventDialog
					open={eventSelected !== null || false}
					onOpenChange={(open) => {
						setEventSelected((e) => (open ? e : null));
					}}
					event={eventSelected}
					onSubmitEvent={ (eventForm) => {
						console.log("Event form: " + eventForm)
					}}
					onDelete={async () => {
						calendar?.events?.remove(eventSelected.id);
						try {
							const res = await request<undefined>(
								`/events/${eventSelected.id}/delete`,
								{
									method: "DELETE",
									body: eventSelected,
									requiresAuth: false,
									csrfToken: false,
								},
							);
							if (res.status === "Error") {
								console.log("Error");
							}
							if (res.status === "Success") {
								console.log("Success");
							}
						} catch (e) {
							console.log(e);
						}
						setEventSelected(null);
					}}
					onUpdate={async () => {
						await handleEventUpdate(eventSelected);
						setEventSelected(null);
					}}
				/>
			)}
		</div>
	);
};

const EventDialog: React.FC<
	{
		onSubmitEvent: (eventFormValues: EventFormValues) => void;
		onDelete?: () => void;
		onUpdate?: () => void;
		onAdd?: () => void;
		event: ICalendarEvent | Omit<ICalendarEvent, "id">;
	} & DialogProps
> = ({
	open,
	onOpenChange,
	onSubmitEvent,
	onDelete,
	onUpdate,
	onAdd,
	event,
}) => {
		return (
			<Dialog open={open} onOpenChange={onOpenChange}>
				<DialogContent className="sm:max-w-md">
					<DialogHeader>
						<DialogTitle>{event.title}</DialogTitle>
						<DialogDescription>{event.description}</DialogDescription>
					</DialogHeader>
					<EventForm 
						event={event} 
						onSubmitEvent={onSubmitEvent}/>
					<DialogFooter className="flex flex-row justify-end">
						{onUpdate && (
							<Button
								variant="outline"
								onClick={() => onUpdate()}
								type="submit"
							>
								Actualiser
							</Button>
						)}
						{onDelete && (
							<Button
								variant="destructive"
								onClick={() => onDelete()}
								type="submit"
							>
								Supprimer
							</Button>
						)}
						{onAdd && !onUpdate && !onDelete && (
							<Button onClick={() => onAdd()} type="submit">
								Créer
							</Button>
						)}
					</DialogFooter>
				</DialogContent >
			</Dialog >
		);
	};

export default Planning;
