"use client";

import { useMemo, useState, useTransition } from "react";
import {
  EventParticipationStatus,
  TerminStatus,
  TerminType,
} from "@prisma/client";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import {
  CalendarPlus,
  Check,
  Clock,
  HelpCircle,
  Pencil,
  Users,
  X,
} from "lucide-react";
import { toast } from "sonner";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
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 {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";
import {
  createTerminAdmin,
  updateTerminAdmin,
} from "../../kalender/actions";

type AdminTerminDto = {
  id: string;
  title: string;
  description: string | null;
  type: TerminType;
  status: TerminStatus;
  startDate: string;
  endDate: string;
  allDay: boolean;
  mitbringselListEnabled: boolean;
  requiresRsvp: boolean;
  rsvpDeadline: string | null;
  participantInfo: string | null;
  participations: {
    childId: string;
    status: EventParticipationStatus;
  }[];
};

type ChildDto = {
  id: string;
  name: string;
  familyName: string;
};

export function AdminCalendarManager({
  termine,
  childRows,
}: {
  termine: AdminTerminDto[];
  childRows: ChildDto[];
}) {
  return (
    <div className="flex h-full flex-col gap-6 p-6">
      <div className="flex flex-col justify-between gap-4 lg:flex-row lg:items-center">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">
            Event-Anmeldungen & Ausflüge
          </h1>
          <p className="max-w-2xl text-sm text-muted-foreground">
            Termine verwalten, RSVP aktivieren und den Rücklauf pro Kind
            verfolgen.
          </p>
        </div>
        <TerminFormDialog mode="create" />
      </div>

      {termine.length === 0 ? (
        <div className="rounded-md border border-dashed p-10 text-center">
          <CalendarPlus className="mx-auto h-10 w-10 text-muted-foreground" />
          <h2 className="mt-4 text-lg font-semibold">Noch keine Termine</h2>
          <p className="mt-1 text-sm text-muted-foreground">
            Lege den ersten Termin an, um RSVP-Rückmeldungen einzusammeln.
          </p>
        </div>
      ) : (
        <div className="grid gap-4">
          {termine.map((termin) => (
            <AdminTerminCard
              key={termin.id}
              termin={termin}
              childRows={childRows}
            />
          ))}
        </div>
      )}
    </div>
  );
}

function AdminTerminCard({
  termin,
  childRows,
}: {
  termin: AdminTerminDto;
  childRows: ChildDto[];
}) {
  const stats = useMemo(() => getStats(termin, childRows), [termin, childRows]);

  return (
    <Card className="overflow-hidden">
      <CardHeader className="border-b bg-muted/30">
        <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
          <div className="min-w-0">
            <div className="mb-2 flex flex-wrap gap-2">
              <Badge className={getTypeBadgeClass(termin.type)}>
                {getTypeLabel(termin.type)}
              </Badge>
              <Badge variant={getStatusVariant(termin.status)}>
                {getStatusLabel(termin.status)}
              </Badge>
              {termin.requiresRsvp && (
                <Badge variant="warning">RSVP aktiv</Badge>
              )}
            </div>
            <CardTitle className="text-lg">{termin.title}</CardTitle>
            <CardDescription className="mt-1 flex flex-wrap items-center gap-2">
              <Clock className="h-3.5 w-3.5" />
              {format(new Date(termin.startDate), "dd.MM.yyyy", {
                locale: de,
              })}
              {!termin.allDay && (
                <>
                  <span>·</span>
                  <span>
                    {format(new Date(termin.startDate), "HH:mm", {
                      locale: de,
                    })}{" "}
                    bis{" "}
                    {format(new Date(termin.endDate), "HH:mm", {
                      locale: de,
                    })}
                  </span>
                </>
              )}
            </CardDescription>
          </div>
          <TerminFormDialog mode="edit" termin={termin} />
        </div>
      </CardHeader>

      <CardContent className="grid gap-5 pt-5">
        {termin.description && (
          <p className="whitespace-pre-wrap text-sm text-muted-foreground">
            {termin.description}
          </p>
        )}

        {termin.requiresRsvp ? (
          <div className="grid gap-4">
            <div className="flex flex-col gap-3 rounded-md border bg-amber-50/70 p-4 text-amber-950 sm:flex-row sm:items-center sm:justify-between">
              <div>
                <p className="font-medium">
                  {stats.attending} Zugesagt / {stats.notAttending} Abgesagt /{" "}
                  {stats.pending} Ausstehend
                </p>
                <p className="mt-1 text-sm text-amber-900/80">
                  Frist:{" "}
                  {termin.rsvpDeadline
                    ? format(new Date(termin.rsvpDeadline), "dd.MM.yyyy HH:mm", {
                        locale: de,
                      })
                    : "bis Terminbeginn"}
                </p>
              </div>
              <Users className="h-5 w-5 shrink-0" />
            </div>

            {termin.participantInfo && (
              <div className="rounded-md border border-yellow-300 bg-yellow-50 p-4 text-sm text-yellow-950">
                <span className="font-medium">Hinweis für Teilnehmer: </span>
                {termin.participantInfo}
              </div>
            )}

            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Kind</TableHead>
                  <TableHead>Familie</TableHead>
                  <TableHead>Status</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {childRows.map((child) => {
                  const status = stats.statusByChildId.get(child.id) ?? null;
                  return (
                    <TableRow key={child.id}>
                      <TableCell className="font-medium">{child.name}</TableCell>
                      <TableCell>{child.familyName}</TableCell>
                      <TableCell>
                        <RsvpStatusBadge status={status} />
                      </TableCell>
                    </TableRow>
                  );
                })}
              </TableBody>
            </Table>
          </div>
        ) : (
          <div className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
            Für diesen Termin ist keine Teilnahme-Abfrage aktiv.
          </div>
        )}
      </CardContent>
    </Card>
  );
}

function TerminFormDialog({
  mode,
  termin,
}: {
  mode: "create" | "edit";
  termin?: AdminTerminDto;
}) {
  const [open, setOpen] = useState(false);
  const [requiresRsvp, setRequiresRsvp] = useState(
    termin?.requiresRsvp ?? false,
  );
  const [isPending, startTransition] = useTransition();

  function handleAction(formData: FormData) {
    const startDate = new Date(String(formData.get("startDate")));
    const endDate = new Date(String(formData.get("endDate")));
    const deadlineRaw = String(formData.get("rsvpDeadline") ?? "");
    const hasRsvp = formData.get("requiresRsvp") === "on";

    const payload = {
      title: String(formData.get("title") ?? ""),
      description: String(formData.get("description") ?? ""),
      type: formData.get("type") as TerminType,
      startDate: startDate.toISOString(),
      endDate: endDate.toISOString(),
      allDay: formData.get("allDay") === "on",
      mitbringselListEnabled: formData.get("mitbringselListEnabled") === "on",
      requiresRsvp: hasRsvp,
      rsvpDeadline:
        hasRsvp && deadlineRaw ? new Date(deadlineRaw).toISOString() : null,
      participantInfo: String(formData.get("participantInfo") ?? ""),
    };

    startTransition(async () => {
      const result =
        mode === "edit" && termin
          ? await updateTerminAdmin(termin.id, payload)
          : await createTerminAdmin(payload);

      if (result.error) {
        toast.error(result.error);
        return;
      }

      toast.success(
        mode === "edit" ? "Termin aktualisiert." : "Termin angelegt.",
      );
      setOpen(false);
    });
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(nextOpen) => {
        setOpen(nextOpen);
        if (nextOpen) {
          setRequiresRsvp(termin?.requiresRsvp ?? false);
        }
      }}
    >
      <DialogTrigger asChild>
        <Button variant={mode === "edit" ? "outline" : "default"} size="sm">
          {mode === "edit" ? (
            <Pencil className="h-4 w-4" />
          ) : (
            <CalendarPlus className="h-4 w-4" />
          )}
          {mode === "edit" ? "Bearbeiten" : "Termin anlegen"}
        </Button>
      </DialogTrigger>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-2xl">
        <form action={handleAction}>
          <DialogHeader>
            <DialogTitle>
              {mode === "edit" ? "Termin bearbeiten" : "Termin anlegen"}
            </DialogTitle>
            <DialogDescription>
              RSVP kann für Ausflüge und besondere Events aktiviert werden.
            </DialogDescription>
          </DialogHeader>

          <div className="grid gap-4 py-4">
            <div className="grid gap-2">
              <Label htmlFor={`${mode}-title`}>Titel</Label>
              <Input
                id={`${mode}-title`}
                name="title"
                defaultValue={termin?.title ?? ""}
                required
              />
            </div>

            <div className="grid gap-2">
              <Label htmlFor={`${mode}-description`}>Beschreibung</Label>
              <Textarea
                id={`${mode}-description`}
                name="description"
                defaultValue={termin?.description ?? ""}
                rows={3}
              />
            </div>

            <div className="grid gap-2">
              <Label htmlFor={`${mode}-type`}>Kategorie</Label>
              <select
                id={`${mode}-type`}
                name="type"
                defaultValue={termin?.type ?? TerminType.KITA_FEST}
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
                required
              >
                {Object.values(TerminType).map((type) => (
                  <option key={type} value={type}>
                    {getTypeLabel(type)}
                  </option>
                ))}
              </select>
            </div>

            <div className="grid gap-4 sm:grid-cols-2">
              <div className="grid gap-2">
                <Label htmlFor={`${mode}-startDate`}>Start</Label>
                <Input
                  id={`${mode}-startDate`}
                  name="startDate"
                  type="datetime-local"
                  defaultValue={
                    termin ? toDatetimeLocalValue(termin.startDate) : ""
                  }
                  required
                />
              </div>
              <div className="grid gap-2">
                <Label htmlFor={`${mode}-endDate`}>Ende</Label>
                <Input
                  id={`${mode}-endDate`}
                  name="endDate"
                  type="datetime-local"
                  defaultValue={
                    termin ? toDatetimeLocalValue(termin.endDate) : ""
                  }
                  required
                />
              </div>
            </div>

            <div className="grid gap-3 rounded-md border p-4">
              <label className="flex items-center gap-2 text-sm">
                <input
                  type="checkbox"
                  name="allDay"
                  defaultChecked={termin?.allDay ?? false}
                  className="h-4 w-4 rounded border-input"
                />
                Ganztägiger Termin
              </label>
              <label className="flex items-center gap-2 text-sm">
                <input
                  type="checkbox"
                  name="mitbringselListEnabled"
                  defaultChecked={termin?.mitbringselListEnabled ?? false}
                  className="h-4 w-4 rounded border-input"
                />
                Mitbring-Liste aktiv
              </label>
              <label className="flex items-center gap-2 text-sm">
                <input
                  type="checkbox"
                  name="requiresRsvp"
                  checked={requiresRsvp}
                  onChange={(event) => setRequiresRsvp(event.target.checked)}
                  className="h-4 w-4 rounded border-input"
                />
                Teilnahme-Abfrage (RSVP) aktivieren
              </label>
            </div>

            {requiresRsvp && (
              <div className="grid gap-4 rounded-md border border-amber-200 bg-amber-50/60 p-4">
                <div className="grid gap-2">
                  <Label htmlFor={`${mode}-rsvpDeadline`}>
                    Rückmeldefrist
                  </Label>
                  <Input
                    id={`${mode}-rsvpDeadline`}
                    name="rsvpDeadline"
                    type="datetime-local"
                    defaultValue={
                      termin?.rsvpDeadline
                        ? toDatetimeLocalValue(termin.rsvpDeadline)
                        : ""
                    }
                  />
                </div>
                <div className="grid gap-2">
                  <Label htmlFor={`${mode}-participantInfo`}>
                    Hinweise für Teilnehmer
                  </Label>
                  <Textarea
                    id={`${mode}-participantInfo`}
                    name="participantInfo"
                    defaultValue={termin?.participantInfo ?? ""}
                    placeholder="z.B. Zweite Brotdose mitbringen"
                    rows={3}
                  />
                </div>
              </div>
            )}
          </div>

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

function RsvpStatusBadge({
  status,
}: {
  status: EventParticipationStatus | null;
}) {
  if (status === EventParticipationStatus.ATTENDING) {
    return (
      <Badge variant="success" className="gap-1">
        <Check className="h-3.5 w-3.5" />
        Zugesagt
      </Badge>
    );
  }

  if (status === EventParticipationStatus.NOT_ATTENDING) {
    return (
      <Badge variant="destructive" className="gap-1">
        <X className="h-3.5 w-3.5" />
        Abgesagt
      </Badge>
    );
  }

  return (
    <Badge variant="outline" className="gap-1 text-muted-foreground">
      <HelpCircle className="h-3.5 w-3.5" />
      Ausstehend
    </Badge>
  );
}

function getStats(termin: AdminTerminDto, children: ChildDto[]) {
  const statusByChildId = new Map(
    termin.participations.map((participation) => [
      participation.childId,
      participation.status,
    ]),
  );

  let attending = 0;
  let notAttending = 0;

  children.forEach((child) => {
    const status = statusByChildId.get(child.id);
    if (status === EventParticipationStatus.ATTENDING) attending += 1;
    if (status === EventParticipationStatus.NOT_ATTENDING) notAttending += 1;
  });

  return {
    attending,
    notAttending,
    pending: Math.max(children.length - attending - notAttending, 0),
    statusByChildId,
  };
}

function toDatetimeLocalValue(value: string) {
  const date = new Date(value);
  const localDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
  return localDate.toISOString().slice(0, 16);
}

function getStatusVariant(
  status: TerminStatus,
): "default" | "secondary" | "destructive" | "outline" | "success" | "warning" {
  switch (status) {
    case TerminStatus.CONFIRMED:
      return "success";
    case TerminStatus.PENDING:
      return "warning";
    case TerminStatus.REJECTED:
    case TerminStatus.CANCELLED:
      return "destructive";
    default:
      return "outline";
  }
}

function getStatusLabel(status: TerminStatus) {
  switch (status) {
    case TerminStatus.CONFIRMED:
      return "Bestätigt";
    case TerminStatus.PENDING:
      return "Ausstehend";
    case TerminStatus.REJECTED:
      return "Abgelehnt";
    case TerminStatus.CANCELLED:
      return "Abgesagt";
  }
}

function getTypeBadgeClass(type: TerminType) {
  switch (type) {
    case TerminType.KITA_FEST:
    case TerminType.MITMACH_TAG:
      return "border-transparent bg-amber-500 text-white";
    case TerminType.SCHLIESSTAG:
    case TerminType.TEAMTAG:
      return "border-transparent bg-rose-500 text-white";
    case TerminType.GEBURTSTAG_INTERN:
    case TerminType.GEBURTSTAG_EXTERN:
      return "border-transparent bg-blue-500 text-white";
    case TerminType.ELTERNABEND:
    case TerminType.MITGLIEDERVERSAMMLUNG:
    case TerminType.ELTERNCAFE:
      return "border-transparent bg-purple-500 text-white";
    default:
      return "border-slate-300 bg-slate-100 text-slate-800";
  }
}

function getTypeLabel(type: TerminType) {
  switch (type) {
    case TerminType.KITA_FEST:
      return "Kita-Fest";
    case TerminType.SCHLIESSTAG:
      return "Schließtag";
    case TerminType.TEAMTAG:
      return "Teamtag";
    case TerminType.MITMACH_TAG:
      return "Mitmach-Tag";
    case TerminType.ELTERNABEND:
      return "Elternabend";
    case TerminType.MITGLIEDERVERSAMMLUNG:
      return "Mitgliederversammlung";
    case TerminType.ELTERNCAFE:
      return "Elterncafe";
    case TerminType.GEBURTSTAG_INTERN:
      return "Geburtstag Intern";
    case TerminType.GEBURTSTAG_EXTERN:
      return "Raumanfrage Extern";
    case TerminType.SONSTIGES:
      return "Sonstiges";
  }
}
