"use client";

import { ApiResponse, request, useApi } 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 {
	CalendarEventExternal,
	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 { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { KeyedMutator } from "swr";

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

	const handleEventUpdate = async (eventSelected: CalendarEventExternal) => {
		const event: CalendarEventExternal = {
			...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") {
				console.log("Error");
			}
			if (res.status === "Success") {
				calendar?.events?.update(eventSelected);
			}
		} catch (e) {
			console.log(e);
		}
	};

	const calendar = useNextCalendarApp(
		{
			theme: "shadcn",
			views: [createViewDay(), createViewWeek()],
			defaultView: "week",
			isDark: true,
			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);
				},
				async onEventUpdate(event) {
					await handleEventUpdate(event);
				},
			},
		},
		plugins,
	);

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

	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}
					onStartChange={(e) => {
						const val = e.currentTarget.value;
						setNewEvent((ev) => {
							if (ev)
								return {
									...ev,
									start: val,
								};
							return ev;
						});
					}}
					onEndChange={(e) => {
						const val = e.currentTarget.value;
						setNewEvent((ev) => {
							if (ev)
								return {
									...ev,
									end: val,
								};
							return ev;
						});
					}}
					onAdd={async () => {
						try {
							const event: Omit<CalendarEventExternal, "id"> = {
								...newEvent,
								start: `${new Date(newEvent.start).toISOString()}`,
								end: `${new Date(newEvent.end).toISOString()}`,
							};
							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}
					onStartChange={(e) => {
						const val = e.currentTarget.value;
						setEventSelected((ev) => {
							if (ev)
								return {
									...ev,
									start: val,
								};
							return ev;
						});
					}}
					onEndChange={(e) => {
						const val = e.currentTarget.value;
						setEventSelected((ev) => {
							if (ev)
								return {
									...ev,
									end: val,
								};
							return ev;
						});
					}}
					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<
	{
		onEndChange: React.ChangeEventHandler<HTMLInputElement>;
		onStartChange: React.ChangeEventHandler<HTMLInputElement>;
		onDelete?: () => void;
		onUpdate?: () => void;
		onAdd?: () => void;
		event: CalendarEventExternal | Omit<CalendarEventExternal, "id">;
	} & DialogProps
> = ({
	open,
	onOpenChange,
	onEndChange,
	onStartChange,
	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>

				<div className="grid gap-4 py-4">
					<div className="grid grid-cols-4 items-center gap-4">
						<Label htmlFor="start" className="text-right">
							Début
						</Label>
						{/*<Popover>
								<PopoverTrigger asChild>
									<Button
										variant={"outline"}
										className={cn(
											"w-[240px] pl-3 text-left font-normal",
											!eventSelected?.start &&
												"text-muted-foreground",
										)}
									>
										{eventSelected?.start ? (
											format(eventSelected?.start, "PPP")
										) : (
											<span>Choisissez une date.</span>
										)}
										<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
									</Button>
								</PopoverTrigger>
								<PopoverContent
									className="w-auto p-0"
									align="start"
								>
									<Calendar
										mode="single"
										selected={
											new Date(
												eventSelected?.start ??
													Date.now(),
											)
										}
										// onSelect={field.onChange}
										disabled={(date) =>
											date > new Date() ||
											date < new Date("1900-01-01")
										}
										initialFocus
									/>
								</PopoverContent>
							</Popover> */}
						<Input
							id="start"
							value={event.start || ""}
							onChange={onStartChange}
							className="col-span-3"
						/>
					</div>
					<div className="grid grid-cols-4 items-center gap-4">
						<Label htmlFor="end" className="text-right">
							Fin
						</Label>
						<Input
							id="end"
							value={event.end || ""}
							onChange={onEndChange}
							className="col-span-3"
						/>
					</div>
				</div>
				<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;
