"use client";

import type { ComponentProps, FormEvent } from "react";
import { useEffect, useMemo, useState, useTransition } from "react";
import { TerminType } from "@prisma/client";
import { Plus } 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 { createTerminAdmin, updateTerminAdmin } from "../actions";
import { Textarea } from "@/components/ui/textarea";

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

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

type AdminTerminModalProps = {
  triggerLabel?: string;
  triggerVariant?: ComponentProps<typeof Button>["variant"];
  triggerClassName?: string;
  existingTermin?: {
    id: string;
    title: string;
    description: string | null;
    type: TerminType;
    startDate: Date;
    endDate: Date;
    allDay: boolean;
  };
};

export function AdminTerminModal({
  triggerLabel = "Termin direkt anlegen",
  triggerVariant,
  triggerClassName = "gap-2",
  existingTermin,
}: AdminTerminModalProps) {
  const [open, setOpen] = useState(false);
  const [formState, setFormState] = useState<AdminTerminFormState>(initialFormState);
  const [isPending, startTransition] = useTransition();
  const minDateTime = useMemo(() => getLocalDateTimeInputValue(new Date()), []);
  const minEndDateTime = formState.startDate || minDateTime;

  // Initialize and reset form fields when modal opens
  useEffect(() => {
    if (open) {
      if (existingTermin) {
        // eslint-disable-next-line react-hooks/set-state-in-effect
        setFormState({
          title: existingTermin.title,
          description: existingTermin.description || "",
          type: existingTermin.type,
          startDate: getLocalDateTimeInputValue(existingTermin.startDate),
          endDate: getLocalDateTimeInputValue(existingTermin.endDate),
          allDay: existingTermin.allDay,
        });
      } else {
        setFormState(initialFormState);
      }
    }
  }, [open, existingTermin]);

  const updateField = <TKey extends keyof AdminTerminFormState>(
    key: TKey,
    value: AdminTerminFormState[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;
    }
    // Only enforce future start date when creating a new event
    if (!existingTermin && 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,
      description: formState.description,
      type: formState.type,
      startDate: new Date(formState.startDate).toISOString(),
      endDate: new Date(formState.endDate).toISOString(),
      allDay: formState.allDay,
    };

    startTransition(async () => {
      let res;
      if (existingTermin) {
        res = await updateTerminAdmin(existingTermin.id, data);
      } else {
        res = await createTerminAdmin(data);
      }

      if (res.error) {
        toast.error(res.error);
      } else {
        toast.success(
          existingTermin
            ? "Termin wurde erfolgreich aktualisiert!"
            : "Termin wurde direkt angelegt!"
        );
        if (!existingTermin) {
          setFormState(initialFormState);
        }
        setOpen(false);
      }
    });
  };

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button variant={triggerVariant} className={triggerClassName}>
          {!existingTermin && <Plus className="h-4 w-4" />}
          {triggerLabel}
        </Button>
      </DialogTrigger>
      <DialogContent>
        <form onSubmit={handleSubmit}>
          <DialogHeader>
            <DialogTitle>
              {existingTermin ? "Termin bearbeiten (Admin)" : "Termin anlegen (Admin)"}
            </DialogTitle>
            <DialogDescription>
              {existingTermin
                ? "Nimm Änderungen an diesem Termin vor. Die Änderungen werden sofort wirksam."
                : "Dieser Termin wird sofort freigegeben und ist für alle sichtbar."}
            </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. Sommerfest"
                value={formState.title}
                onChange={(event) => updateField("title", event.target.value)}
              />
            </div>

            <div className="grid gap-2">
              <Label htmlFor="description">Beschreibung (Optional)</Label>
              <Textarea
                id="description"
                name="description"
                placeholder="Details zum Termin..."
                value={formState.description}
                onChange={(event) => updateField("description", 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)]"
                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={existingTermin ? undefined : 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={formState.startDate || (existingTermin ? undefined : minDateTime)}
                  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 ? "Speichern..." : existingTermin ? "Änderungen speichern" : "Termin erstellen"}
            </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);
}
