"use client";

import { format, parseISO } from "date-fns";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "@/components/ui/select";
import {
	getRecurrencePreview,
	getWeekdayOptions,
	parseRecurrenceRule,
	type RecurrenceFormValue,
	recurrenceFrequencyLabels,
	type SupportedRecurrenceFrequency,
	serializeRecurrenceRule,
	validateRecurrence,
	type Weekday,
} from "@/lib/recurrence";

interface Props {
	value?: string;
	start?: string;
	onChange: (rrule: string | undefined) => void;
}

const weekdayOptions = getWeekdayOptions();

const getStartWeekday = (start?: string): Weekday => {
	if (!start) return "MO";
	const parsed = parseISO(start);
	const jsDay = parsed.getDay();
	const weekdays: Weekday[] = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
	return weekdays[jsDay] ?? "MO";
};

const updateWeekdays = (current: Weekday[], day: Weekday): Weekday[] => {
	return current.includes(day)
		? current.filter((existingDay) => existingDay !== day)
		: [...current, day];
};

export function RecurrencePicker({ value, start, onChange }: Props) {
	const recurrence = parseRecurrenceRule(value);
	const validation = validateRecurrence(recurrence);
	const preview = start ? getRecurrencePreview(recurrence, start, 3) : [];

	const update = (updates: Partial<RecurrenceFormValue>) => {
		const nextValue = { ...recurrence, ...updates };

		if (nextValue.freq === "NONE") {
			onChange(undefined);
			return;
		}

		const nextValidation = validateRecurrence(nextValue);
		if (!nextValidation.isValid && nextValidation.errors.rule) {
			onChange(value);
			return;
		}

		onChange(serializeRecurrenceRule(nextValue, start));
	};

	return (
		<div className="space-y-3">
			<div>
				<Label htmlFor="frequency" className="text-xs text-muted-foreground">
					Repeats
				</Label>
				<Select
					value={recurrence.freq}
					onValueChange={(nextFrequency) => {
						const frequency = nextFrequency as SupportedRecurrenceFrequency;
						update({
							freq: frequency,
							byDay:
								frequency === "WEEKLY"
									? recurrence.byDay.length > 0
										? recurrence.byDay
										: [getStartWeekday(start)]
									: [],
						});
					}}
				>
					<SelectTrigger id="frequency" className="mt-1.5">
						<SelectValue />
					</SelectTrigger>
					<SelectContent>
						{Object.entries(recurrenceFrequencyLabels).map(
							([optionValue, label]) => (
								<SelectItem key={optionValue} value={optionValue}>
									{label}
								</SelectItem>
							),
						)}
					</SelectContent>
				</Select>
			</div>

			{recurrence.freq !== "NONE" && (
				<>
					<div>
						<Label htmlFor="interval" className="text-xs text-muted-foreground">
							Interval (every {recurrence.interval}{" "}
							{recurrence.freq === "DAILY"
								? "day"
								: recurrence.freq === "WEEKLY"
									? "week"
									: "month"}
							{recurrence.interval > 1 ? "s" : ""})
						</Label>
						<Input
							id="interval"
							type="number"
							min={1}
							value={recurrence.interval}
							onChange={(event) =>
								update({
									interval: Number.parseInt(event.target.value, 10) || 1,
								})
							}
							className="mt-1.5 w-24"
						/>
					</div>

					{recurrence.freq === "WEEKLY" && (
						<div>
							<Label className="text-xs text-muted-foreground">
								Days of the week
							</Label>
							<div className="mt-1.5 flex flex-wrap gap-3">
								{weekdayOptions.map(({ value: day, label }) => (
									<div key={day} className="flex items-center gap-1.5">
										<Checkbox
											id={day}
											checked={recurrence.byDay.includes(day)}
											onCheckedChange={() =>
												update({ byDay: updateWeekdays(recurrence.byDay, day) })
											}
										/>
										<Label
											htmlFor={day}
											className="cursor-pointer text-xs font-normal"
										>
											{label}
										</Label>
									</div>
								))}
							</div>
						</div>
					)}

					<div className="grid grid-cols-2 gap-3">
						<div>
							<Label htmlFor="count" className="text-xs text-muted-foreground">
								End after (occurrences)
							</Label>
							<Input
								id="count"
								type="number"
								placeholder="e.g. 10"
								value={recurrence.count || ""}
								onChange={(event) =>
									update({
										count: event.target.value
											? Number.parseInt(event.target.value, 10)
											: undefined,
										until: event.target.value ? undefined : recurrence.until,
									})
								}
								className="mt-1.5"
							/>
						</div>
						<div>
							<Label htmlFor="until" className="text-xs text-muted-foreground">
								End by date
							</Label>
							<Input
								id="until"
								type="date"
								value={recurrence.until || ""}
								onChange={(event) =>
									update({
										until: event.target.value || undefined,
										count: event.target.value ? undefined : recurrence.count,
									})
								}
								className="mt-1.5"
							/>
						</div>
					</div>

					{validation.errors.count && (
						<p className="text-xs text-destructive">
							{validation.errors.count}
						</p>
					)}
					{validation.errors.until && (
						<p className="text-xs text-destructive">
							{validation.errors.until}
						</p>
					)}
					{validation.errors.rule && (
						<p className="text-xs text-destructive">{validation.errors.rule}</p>
					)}

					{preview.length > 0 && (
						<div className="rounded-md border border-border/70 bg-muted/35 px-3 py-2">
							<p className="text-xs font-medium text-foreground">Upcoming</p>
							<p className="mt-1 text-xs text-muted-foreground">
								{preview
									.map((entry) => format(parseISO(entry), "EEE, MMM d"))
									.join(" · ")}
							</p>
						</div>
					)}
				</>
			)}
		</div>
	);
}
