"use client";

import type { ComponentProps, FormEvent } from "react";
import { useMemo, useState, useTransition } from "react";
import { TerminType } from "@prisma/client";
import { CalendarPlus } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { createTerminRequest } from "../actions";

type TerminRequestFormState = {
  title: string;
  type: TerminType;
  startDate: string;
  endDate: string;
  allDay: boolean;
};

const initialFormState: TerminRequestFormState = {
  title: "",
  type: TerminType.KITA_FEST,
  startDate: "",
  endDate: "",
  allDay: false,
};

type TerminRequestModalProps = {
  triggerLabel?: string;
  triggerVariant?: ComponentProps<typeof Button>["variant"];
  triggerClassName?: string;
};

export function TerminRequestModal({
  triggerLabel = "Termin anfragen",
  triggerVariant = "ghost",
  triggerClassName = "gap-2",
}: TerminRequestModalProps) {
  const [open, setOpen] = useState(false);
  const [formState, setFormState] = useState<TerminRequestFormState>(initialFormState);
  const [isPending, startTransition] = useTransition();
  const minDateTime = useMemo(() => getLocalDateTimeInputValue(new Date()), []);
  const minEndDateTime = formState.startDate || minDateTime;

  const updateField = <TKey extends keyof TerminRequestFormState>(
    key: TKey,
    value: TerminRequestFormState[TKey],
  ) => {
    setFormState((current) => {
      const next = { ...current, [key]: value };
      if (key === "startDate" && typeof value === "string" && next.endDate && next.endDate < value) {
        next.endDate = value;
      }
      return next;
    });
  };

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (!formState.startDate || !formState.endDate) {
      toast.error("Bitte Start und Ende ausfüllen.");
      return;
    }
    if (formState.startDate < minDateTime) {
      toast.error("Der Startzeitpunkt darf nicht in der Vergangenheit liegen.");
      return;
    }
    if (formState.endDate < formState.startDate) {
      toast.error("Das Ende darf nicht vor dem Start liegen.");
      return;
    }

    const data = {
      title: formState.title,
      type: formState.type,
      startDate: new Date(formState.startDate).toISOString(),
      endDate: new Date(formState.endDate).toISOString(),
      allDay: formState.allDay,
    };

    startTransition(async () => {
      const res = await createTerminRequest(data);
      if (res.error) {
        toast.error(res.error);
      } else {
        toast.success("Terminanfrage wurde erfolgreich gestellt!");
        setFormState(initialFormState);
        setOpen(false);
      }
    });
  };

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button variant={triggerVariant} className={triggerClassName}>
          <CalendarPlus className="h-4 w-4 [stroke-width:1.7]" />
          {triggerLabel}
        </Button>
      </DialogTrigger>
      <DialogContent>
        <form onSubmit={handleSubmit}>
          <DialogHeader>
            <DialogTitle>Termin anfragen</DialogTitle>
            <DialogDescription>
              Frage einen privaten Termin (z.B. Kindergeburtstag) in den Räumlichkeiten der Kita an.
              Die Anfrage muss von einem Admin bestätigt werden.
            </DialogDescription>
          </DialogHeader>

          <div className="grid gap-4 py-4">
            <div className="grid gap-2">
              <Label htmlFor="title">Titel</Label>
              <Input
                id="title"
                name="title"
                required
                placeholder="z.B. Geburtstag von Mia"
                value={formState.title}
                onChange={(event) => updateField("title", event.target.value)}
              />
            </div>

            <div className="grid gap-2">
              <Label htmlFor="type">Kategorie</Label>
              <select
                id="type"
                name="type"
                value={formState.type}
                className="flex h-10 w-full rounded-lg border border-[var(--hairline)] bg-[var(--surface)] px-3 py-2 text-[13.5px] text-[var(--ink)] ring-offset-[var(--surface)] transition-colors hover:border-[var(--accent-mid)] focus-visible:border-[var(--accent)] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--focus-ring)] disabled:cursor-not-allowed disabled:opacity-50"
                onChange={(event) => updateField("type", event.target.value as TerminType)}
                required
              >
                <option value={TerminType.KITA_FEST}>Kita-Fest</option>
                <option value={TerminType.SCHLIESSTAG}>Schließtag</option>
                <option value={TerminType.TEAMTAG}>Teamtag (Kita geschlossen)</option>
                <option value={TerminType.MITMACH_TAG}>Mitmach-Tag</option>
                <option value={TerminType.ELTERNABEND}>Elternabend</option>
                <option value={TerminType.MITGLIEDERVERSAMMLUNG}>Mitgliederversammlung</option>
                <option value={TerminType.ELTERNCAFE}>Elterncafe</option>
                <option value={TerminType.GEBURTSTAG_INTERN}>Geburtstag (Intern)</option>
                <option value={TerminType.GEBURTSTAG_EXTERN}>Raumanfrage (Extern)</option>
                <option value={TerminType.SONSTIGES}>Sonstiges</option>
              </select>
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div className="grid gap-2">
                <Label htmlFor="startDate">Start</Label>
                <Input
                  id="startDate"
                  name="startDate"
                  type="datetime-local"
                  min={minDateTime}
                  value={formState.startDate}
                  onChange={(event) => updateField("startDate", event.target.value)}
                  required
                />
              </div>
              <div className="grid gap-2">
                <Label htmlFor="endDate">Ende</Label>
                <Input
                  id="endDate"
                  name="endDate"
                  type="datetime-local"
                  min={minEndDateTime}
                  value={formState.endDate}
                  onChange={(event) => updateField("endDate", event.target.value)}
                  required
                />
              </div>
            </div>

            <div className="flex items-center gap-2 mt-2">
              <input
                type="checkbox"
                id="allDay"
                name="allDay"
                checked={formState.allDay}
                className="rounded border-[var(--hairline)] accent-[var(--accent-deep)]"
                onChange={(event) => updateField("allDay", event.target.checked)}
              />
              <Label htmlFor="allDay" className="font-normal cursor-pointer">
                Ganztägiger Termin
              </Label>
            </div>
          </div>

          <DialogFooter>
            <Button type="button" variant="ghost" onClick={() => setOpen(false)}>
              Abbrechen
            </Button>
            <Button type="submit" disabled={isPending}>
              {isPending ? "Wird gesendet..." : "Anfrage stellen"}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

function getLocalDateTimeInputValue(date: Date) {
  const localDate = new Date(date);
  localDate.setSeconds(0, 0);
  const offset = localDate.getTimezoneOffset() * 60_000;
  return new Date(localDate.getTime() - offset).toISOString().slice(0, 16);
}
