import { isAfter, parseISO } from "date-fns";
import { z } from "zod";
import type { CalendarEvent } from "@/lib/types";

export interface EventFormValues {
	title: string;
	description: string;
	location: string;
	url: string;
	start: string;
	end: string;
	allDay: boolean;
	recurrenceRule?: string;
}

const eventFormSchema = z
	.object({
		title: z.string().trim().min(1, "Title is required."),
		description: z.string(),
		location: z.string(),
		url: z.preprocess((value) => value ?? "", z.string().trim()),
		start: z.string().trim().min(1, "Start date is required."),
		end: z.string(),
		allDay: z.boolean(),
		recurrenceRule: z.string().optional(),
	})
	.superRefine((value, ctx) => {
		if (value.url) {
			const urlValidation = z.string().url().safeParse(value.url);
			if (!urlValidation.success) {
				ctx.addIssue({
					code: z.ZodIssueCode.custom,
					path: ["url"],
					message: "Enter a valid URL.",
				});
			}
		}

		if (value.end) {
			const startDate = parseISO(value.start);
			const endDate = parseISO(value.end);
			if (
				Number.isNaN(startDate.getTime()) ||
				Number.isNaN(endDate.getTime())
			) {
				ctx.addIssue({
					code: z.ZodIssueCode.custom,
					path: ["end"],
					message: "End date must be valid.",
				});
			} else if (!isAfter(endDate, startDate)) {
				ctx.addIssue({
					code: z.ZodIssueCode.custom,
					path: ["end"],
					message: "End date must be after the start date.",
				});
			}
		}
	});

export const getDefaultEventFormValues = (): EventFormValues => ({
	title: "",
	description: "",
	location: "",
	url: "",
	start: "",
	end: "",
	allDay: false,
	recurrenceRule: undefined,
});

export const getEventFormValuesFromEvent = (
	event?: Partial<CalendarEvent>,
): EventFormValues => ({
	...getDefaultEventFormValues(),
	title: event?.title || "",
	description: event?.description || "",
	location: event?.location || "",
	url: event?.url || "",
	start: event?.start || "",
	end: event?.end || "",
	allDay: event?.allDay || false,
	recurrenceRule: event?.recurrenceRule || undefined,
});

export const getEventValidationIssues = (
	event: Pick<CalendarEvent, "start" | "end" | "url">,
) => {
	const issues: string[] = [];

	if (event.end) {
		const startDate = new Date(event.start);
		const endDate = new Date(event.end);

		if (
			!Number.isNaN(startDate.getTime()) &&
			!Number.isNaN(endDate.getTime()) &&
			endDate.getTime() < startDate.getTime()
		) {
			issues.push("end time is before start time");
		}
	}

	if (event.url && !URL.canParse(event.url)) {
		issues.push("link is invalid");
	}

	return issues;
};

export const validateEventFormValues = (values: EventFormValues) =>
	eventFormSchema.safeParse(values);
