"use client";
import { useEffect } from "react";
import { CheckCircledIcon, EnterIcon, DrawingPinFilledIcon } from "@radix-ui/react-icons";
import { Event, EventAppointment, Participant, User } from "@repo/db";
import { cn } from "@repo/shared-components";
import { inscribeToMoodleCourse, upsertParticipant } from "../actions";
import {
	BookCheck,
	Calendar,
	Check,
	CirclePlay,
	Clock10Icon,
	ExternalLink,
	EyeIcon,
	Info,
	TriangleAlert,
} from "lucide-react";
import { useForm } from "react-hook-form";
import {
	InputJsonValueType,
	ParticipantOptionalDefaults,
	ParticipantOptionalDefaultsSchema,
} from "@repo/db/zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Select } from "../../../_components/ui/Select";
import { useRouter } from "next/navigation";
import { handleParticipantEnrolled } from "../../../../helper/events";
import { eventCompleted } from "@repo/shared-components";
import MDEditor from "@uiw/react-md-editor";
import toast from "react-hot-toast";
import { formatDate } from "date-fns";

interface ModalBtnProps {
	title: string;
	event: Event;
	dates: (EventAppointment & {
		Participants: { userId: string }[];
	})[];
	selectedAppointments: EventAppointment[];
	participant?: Participant;
	user: User;
	modalId: string;
}

const ModalBtn = ({
	title,
	dates,
	modalId,
	participant,
	selectedAppointments,
	event,
	user,
}: ModalBtnProps) => {
	useEffect(() => {
		const modal = document.getElementById(modalId) as HTMLDialogElement;
		const handleOpen = () => {
			document.body.classList.add("modal-open");
		};
		const handleClose = () => {
			document.body.classList.remove("modal-open");
		};
		modal?.addEventListener("show", handleOpen);
		modal?.addEventListener("close", handleClose);
		return () => {
			modal?.removeEventListener("show", handleOpen);
			modal?.removeEventListener("close", handleClose);
		};
	}, [modalId]);
	const router = useRouter();

	const canSelectDate =
		event.hasPresenceEvents &&
		!participant?.attended &&
		(selectedAppointments.length === 0 || participant?.appointmentCancelled);

	const openModal = () => {
		const modal = document.getElementById(modalId) as HTMLDialogElement;
		modal?.showModal();
	};

	const closeModal = () => {
		const modal = document.getElementById(modalId) as HTMLDialogElement;
		modal?.close();
	};
	const selectAppointmentForm = useForm<ParticipantOptionalDefaults>({
		resolver: zodResolver(ParticipantOptionalDefaultsSchema),
		defaultValues: {
			eventId: event.id,
			userId: user.id,
			...participant,
		},
	});
	const selectedAppointment = selectedAppointments[0];
	const selectedDate = dates.find(
		(date) =>
			date.id === selectAppointmentForm.watch("eventAppointmentId") || selectedAppointment?.id,
	);
	const ownIndexInParticipantList = selectedDate?.Participants?.findIndex(
		(p) => p.userId === user.id,
	);

	const ownPlaceInParticipantList =
		typeof ownIndexInParticipantList === "number"
			? ownIndexInParticipantList === -1
				? (selectedDate?.Participants?.length ?? 0) + 1
				: ownIndexInParticipantList + 1
			: undefined;

	const missingRequirements =
		event.requiredBadges?.length > 0 &&
		!event.requiredBadges.some((badge) => user.badges.includes(badge));

	return (
		<>
			<button
				className={cn(
					"btn btn-outline btn-info btn-wide",
					event.type === "COURSE" && "btn-secondary",
					eventCompleted(event, participant) && "btn-success",
				)}
				onClick={openModal}
				disabled={eventCompleted(event, participant) || missingRequirements}
			>
				{missingRequirements && (
					<>
						<TriangleAlert className="h-6 w-6 shrink-0 stroke-current" fill="none" />
						fehlende Anforderungen
					</>
				)}
				{participant && !eventCompleted(event, participant) && !missingRequirements && (
					<>
						<EyeIcon /> Anzeigen
					</>
				)}
				{!participant && !missingRequirements && (
					<>
						<EnterIcon /> Anmelden
					</>
				)}
				{eventCompleted(event, participant) && (
					<>
						<Check /> Abgeschlossen
					</>
				)}
			</button>
			<dialog id={modalId} className="modal">
				<div className="modal-box w-11/12 max-w-5xl overflow-hidden">
					<form method="dialog">
						<button className="btn btn-sm btn-circle btn-ghost absolute right-3 top-3">✕</button>
					</form>
					<h3 className="font-bold text-lg text-left">{title}</h3>
					<div className="flex flex-wrap gap-4 mt-4">
						<div className="flex flex-col gap-2 flex-1 p-3 bg-base-300 min-w-[300px] shadow rounded-lg">
							<h2 className="flex gap-2 text-lg font-bold">
								<Info /> Details
							</h2>
							<div className="text-left text-balance">
								<MDEditor.Markdown
									source={event.description}
									style={{
										backgroundColor: "transparent",
									}}
								/>
							</div>
						</div>
						{event.hasPresenceEvents && (
							<div className="flex flex-col gap-2 flex-1 p-3 bg-base-300 min-w-[300px] shadow rounded-lg">
								<h2 className="flex gap-2 text-lg font-bold">
									<Calendar /> Termine
								</h2>
								<div className="flex flex-1 flex-col justify-center items-center">
									{!!dates.length && !selectedDate && (
										<>
											<p className="text-center text-info">Melde dich zu einem Termin an</p>
											<Select
												form={selectAppointmentForm}
												options={dates.map((date) => ({
													label: `${formatDate(date.appointmentDate, "dd.MM.yyyy HH:mm")} - (${date.Participants.length}/${event.maxParticipants})`,
													value: date.id,
												}))}
												name="eventAppointmentId"
												label={""}
												placeholder="Wähle einen Termin"
												className="min-w-[250px]"
											/>
										</>
									)}
									{selectedAppointment && !participant?.appointmentCancelled && (
										<div className="flex flex-col items-center justify-center gap-2">
											<span>Dein ausgewählter Termin (Deutsche Zeit)</span>
											<div>
												<button
													className="input input-border min-w-[250px] pointer-events-none"
													style={{ anchorName: "--rdp" } as React.CSSProperties}
												>
													{new Date(selectedAppointment.appointmentDate).toLocaleString("de-DE", {
														year: "numeric",
														month: "2-digit",
														day: "2-digit",
														hour: "2-digit",
														minute: "2-digit",
													})}
												</button>
											</div>
											{participant?.attended ? (
												<p className="py-4 flex items-center gap-2 justify-center">
													<CheckCircledIcon className="text-success" />
													Du hast an dem Presenztermin teilgenommen
												</p>
											) : (
												<p className="py-4 flex items-center gap-2 justify-center">
													Bitte erscheine ~5 minuten vor dem Termin im Discord
												</p>
											)}
										</div>
									)}

									{!dates.length && (
										<p className="text-center text-error">Aktuell sind keine Termine verfügbar</p>
									)}

									{!!selectedDate &&
										!!event.maxParticipants &&
										!!ownPlaceInParticipantList &&
										!!(ownPlaceInParticipantList > event.maxParticipants) && (
											<p
												role="alert"
												className="py-4 my-5 flex items-center gap-2 justify-center border alert alert-error alert-outline"
											>
												<TriangleAlert className="h-6 w-6 shrink-0 stroke-current" fill="none" />
												Dieser Termin ist ausgebucht, wahrscheinlich wirst du nicht teilnehmen
												können. (Listenplatz: {ownPlaceInParticipantList} , max.{" "}
												{event.maxParticipants})
											</p>
										)}
								</div>
							</div>
						)}
						{event.finisherMoodleCourseId && (
							<div className="flex flex-col gap-2 flex-1 p-3 bg-base-300 min-w-[300px] shadow rounded-lg">
								<h2 className="flex gap-2 text-lg font-bold">
									<BookCheck /> Moodle-Kurs
								</h2>
								<div className="flex flex-col items-center justify-center h-full">
									<MoodleCourseIndicator
										participant={participant}
										user={user}
										moodleCourseId={event.finisherMoodleCourseId}
										completed={participant?.finisherMoodleCurseCompleted || false}
										event={event}
									/>
								</div>
							</div>
						)}
					</div>

					<div className="flex justify-between items-end mt-5">
						<div>
							<p className="text-gray-600 text-left flex items-center gap-2">
								<DrawingPinFilledIcon /> <b>Teilnahmevoraussetzungen: </b>
								{!event.requiredBadges.length && "Keine"}
							</p>
						</div>
						<div className="modal-action">
							{!!canSelectDate && (
								<button
									className={cn(
										"btn btn-info btn-outline btn-wide",
										event.type === "COURSE" && "btn-secondary",
									)}
									onClick={async () => {
										const data = selectAppointmentForm.getValues();
										if (!data.eventAppointmentId) return;

										const participant = await upsertParticipant({
											...data,
											enscriptionDate: new Date(),
											statusLog: data.statusLog?.filter((log) => log !== null),
											appointmentCancelled: false,
										});
										await handleParticipantEnrolled(participant.id.toString());

										router.refresh();
										closeModal();
									}}
									disabled={!selectAppointmentForm.watch("eventAppointmentId")}
								>
									<EnterIcon /> Anmelden
								</button>
							)}
							{selectedAppointment &&
								!participant?.appointmentCancelled &&
								!participant?.attended && (
									<button
										onClick={async () => {
											await upsertParticipant({
												eventId: event.id,
												userId: participant!.userId,
												appointmentCancelled: true,
												statusLog: [
													...(participant?.statusLog as unknown as InputJsonValueType[]),
													{
														data: {
															appointmentId: selectedAppointment.id,
															appointmentDate: selectedAppointment.appointmentDate,
														},
														user: `${user?.firstname} ${user?.lastname} - ${user?.publicId}`,
														event: "Termin abgesagt",
														timestamp: new Date(),
													},
												],
											});
											toast.success("Termin abgesagt");
											router.refresh();
										}}
										className="btn btn-error btn-outline btn-wide"
									>
										Termin Absagen
									</button>
								)}
						</div>
					</div>
				</div>
				<button className="modal-backdrop" onClick={closeModal}>
					Abbrechen
				</button>
			</dialog>
		</>
	);
};

export default ModalBtn;

const MoodleCourseIndicator = ({
	completed,
	moodleCourseId,
	event,
	participant,
	user,
}: {
	user: User;
	participant?: Participant;
	completed?: boolean;
	moodleCourseId: string;
	event: Event;
}) => {
	const courseUrl = `${process.env.NEXT_PUBLIC_MOODLE_URL}/course/view.php?id=${moodleCourseId}`;
	if (event.hasPresenceEvents && !participant?.attended)
		return (
			<p className="py-4 flex items-center gap-2 justify-center">
				<Clock10Icon className="text-error" />
				Abschlusstest erst nach Teilnahme verfügbar
			</p>
		);
	if (completed)
		return (
			<p className="py-4 flex items-center gap-2 justify-center">
				<CheckCircledIcon className="text-success" />
				Moodle Kurs abgeschlossen
			</p>
		);
	return (
		<div className="flex flex-col items-center justify-center gap-2">
			<p className="text-sm flex items-center gap-2">
				<CirclePlay className="text-warning" /> Moodle-Kurs bereit
			</p>
			<button
				className="btn btn-sm btn-outline btn-info ml-2"
				onClick={async () => {
					try {
						await upsertParticipant({
							eventId: event.id,
							userId: user.id,
							finisherMoodleCurseCompleted: false,
						});

						if (user.moodleId) {
							await inscribeToMoodleCourse(moodleCourseId, user.moodleId);
						}
						window.open(courseUrl, "_blank");
					} catch (error) {
						console.log("Fehler beim öffnen des Moodle-Kurses", error);
					}
				}}
			>
				<ExternalLink size={16} />
				Zum Moodle Kurs
			</button>
			<p className="text-xs text-gray-400">
				Wenn du nach dem Anmelden den moodle Kurs nicht siehst, warte ein paar Sekunden und lade die
				Seite neu.
			</p>
		</div>
	);
};
