"use client";

import { useMemo, useState, useTransition } from "react";
import { Pencil, Plus, Trash2 } 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 { updateFamilyAction } from "./actions";

type EditableParent = {
  id: string;
  firstName: string;
  lastName: string;
  email: string;
};

type EditableChild = {
  id: string;
  firstName: string;
  lastName: string;
};

type DraftParent = EditableParent & {
  kind: "existing" | "new";
};

type DraftChild = EditableChild & {
  kind: "existing" | "new";
};

type EditableFamily = {
  id: string;
  name: string;
  parents: EditableParent[];
  children: EditableChild[];
};

export function EditFamilyDialog({ family }: { family: EditableFamily }) {
  const [isPending, startTransition] = useTransition();
  const initialParents = useMemo(
    () =>
      family.parents.map((parent) => ({
        ...parent,
        kind: "existing" as const,
      })),
    [family.parents],
  );
  const initialChildren = useMemo(
    () =>
      family.children.map((child) => ({
        ...child,
        kind: "existing" as const,
      })),
    [family.children],
  );
  const [parents, setParents] = useState<DraftParent[]>(initialParents);
  const [children, setChildren] = useState<DraftChild[]>(initialChildren);
  const [removedChildIds, setRemovedChildIds] = useState<string[]>([]);

  function resetState() {
    setParents(initialParents);
    setChildren(initialChildren);
    setRemovedChildIds([]);
  }

  function addParent() {
    if (parents.length >= 2) return;
    setParents((current) => [
      ...current,
      {
        id: `new-parent-${crypto.randomUUID()}`,
        firstName: "",
        lastName: "",
        email: "",
        kind: "new",
      },
    ]);
  }

  function removeNewParent(parent: DraftParent) {
    if (parent.kind !== "new") return;
    setParents((current) => current.filter((item) => item.id !== parent.id));
  }

  function addChild() {
    setChildren((current) => [
      ...current,
      {
        id: `new-child-${crypto.randomUUID()}`,
        firstName: "",
        lastName: "",
        kind: "new",
      },
    ]);
  }

  function removeChild(child: DraftChild) {
    setChildren((current) => current.filter((item) => item.id !== child.id));
    if (child.kind === "existing") {
      setRemovedChildIds((current) => [...current, child.id]);
    }
  }

  function handleSubmit(formData: FormData) {
    const payload = {
      familyId: family.id,
      familyName: String(formData.get("familyName") ?? ""),
      parents: parents
        .filter((parent) => parent.kind === "existing")
        .map((parent) => ({
          id: parent.id,
          firstName: String(formData.get(`parentFirstName_${parent.id}`) ?? ""),
          lastName: String(formData.get(`parentLastName_${parent.id}`) ?? ""),
          email: String(formData.get(`parentEmail_${parent.id}`) ?? ""),
        })),
      newParents: parents
        .filter((parent) => parent.kind === "new")
        .map((parent) => ({
          firstName: String(formData.get(`parentFirstName_${parent.id}`) ?? ""),
          lastName: String(formData.get(`parentLastName_${parent.id}`) ?? ""),
          email: String(formData.get(`parentEmail_${parent.id}`) ?? ""),
        })),
      children: children
        .filter((child) => child.kind === "existing")
        .map((child) => ({
          id: child.id,
          firstName: String(formData.get(`childFirstName_${child.id}`) ?? ""),
          lastName: String(formData.get(`childLastName_${child.id}`) ?? ""),
        })),
      newChildren: children
        .filter((child) => child.kind === "new")
        .map((child) => ({
          firstName: String(formData.get(`childFirstName_${child.id}`) ?? ""),
          lastName: String(formData.get(`childLastName_${child.id}`) ?? ""),
        })),
      removedChildIds,
    };

    startTransition(async () => {
      const result = await updateFamilyAction(payload);
      if (result.error) {
        toast.error(result.error);
        return;
      }

      toast.success("Familie aktualisiert.");
      setRemovedChildIds([]);
    });
  }

  return (
    <Dialog onOpenChange={(open) => !open && resetState()}>
      <DialogTrigger asChild>
        <Button variant="ghost" size="sm" className="h-8 gap-1">
          <Pencil className="h-4 w-4" />
          <span className="hidden sm:inline">Details</span>
        </Button>
      </DialogTrigger>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-2xl">
        <form action={handleSubmit}>
          <DialogHeader>
            <DialogTitle>Familie bearbeiten</DialogTitle>
            <DialogDescription>
              Aktualisiere Haushalt, Elternteile und Kinder.
            </DialogDescription>
          </DialogHeader>

          <div className="grid gap-6 py-4">
            <div className="grid gap-2">
              <Label htmlFor={`familyName-${family.id}`}>Familienname</Label>
              <Input
                id={`familyName-${family.id}`}
                name="familyName"
                defaultValue={family.name}
                required
              />
            </div>

            <fieldset className="grid gap-3">
              <div className="flex items-center justify-between gap-3">
                <legend className="text-sm font-semibold">Elternteile</legend>
                {parents.length < 2 && (
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="h-8 gap-1"
                    onClick={addParent}
                    disabled={isPending}
                  >
                    <Plus className="h-3.5 w-3.5" />
                    Elternteil hinzufügen
                  </Button>
                )}
              </div>

              {parents.map((parent, index) => (
                <div key={parent.id} className="rounded-md border p-3">
                  <div className="mb-3 flex items-center justify-between gap-3">
                    <p className="text-xs font-medium text-muted-foreground">
                      Elternteil {index + 1}
                    </p>
                    {parent.kind === "new" && (
                      <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        className="h-7 gap-1 px-2 text-destructive hover:text-destructive"
                        onClick={() => removeNewParent(parent)}
                        disabled={isPending}
                      >
                        <Trash2 className="h-3.5 w-3.5" />
                        Entfernen
                      </Button>
                    )}
                  </div>
                  <div className="grid gap-3 sm:grid-cols-2">
                    <Field
                      id={`parentFirstName-${parent.id}`}
                      name={`parentFirstName_${parent.id}`}
                      label="Vorname"
                      defaultValue={parent.firstName}
                    />
                    <Field
                      id={`parentLastName-${parent.id}`}
                      name={`parentLastName_${parent.id}`}
                      label="Nachname"
                      defaultValue={parent.lastName}
                    />
                  </div>
                  <div className="mt-3">
                    <Field
                      id={`parentEmail-${parent.id}`}
                      name={`parentEmail_${parent.id}`}
                      label="E-Mail-Adresse"
                      type="email"
                      defaultValue={parent.email}
                    />
                  </div>
                </div>
              ))}
            </fieldset>

            <fieldset className="grid gap-3">
              <div className="flex items-center justify-between gap-3">
                <legend className="text-sm font-semibold">Kinder</legend>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-8 gap-1"
                  onClick={addChild}
                  disabled={isPending}
                >
                  <Plus className="h-3.5 w-3.5" />
                  Kind hinzufügen
                </Button>
              </div>

              {children.length === 0 ? (
                <p className="text-sm text-muted-foreground">
                  Keine Kinder verknüpft.
                </p>
              ) : (
                children.map((child, index) => (
                  <div key={child.id} className="rounded-md border p-3">
                    <div className="mb-3 flex items-center justify-between gap-3">
                      <p className="text-xs font-medium text-muted-foreground">
                        Kind {index + 1}
                      </p>
                      <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        className="h-7 gap-1 px-2 text-destructive hover:text-destructive"
                        onClick={() => removeChild(child)}
                        disabled={isPending}
                      >
                        <Trash2 className="h-3.5 w-3.5" />
                        Entfernen
                      </Button>
                    </div>
                    <div className="grid gap-3 sm:grid-cols-2">
                      <Field
                        id={`childFirstName-${child.id}`}
                        name={`childFirstName_${child.id}`}
                        label="Vorname"
                        defaultValue={child.firstName}
                      />
                      <Field
                        id={`childLastName-${child.id}`}
                        name={`childLastName_${child.id}`}
                        label="Nachname"
                        defaultValue={child.lastName}
                      />
                    </div>
                  </div>
                ))
              )}
            </fieldset>
          </div>

          <DialogFooter>
            <Button type="submit" disabled={isPending}>
              {isPending ? "Speichert..." : "Speichern"}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

function Field({
  id,
  name,
  label,
  type = "text",
  defaultValue,
}: {
  id: string;
  name: string;
  label: string;
  type?: string;
  defaultValue: string;
}) {
  return (
    <div className="grid gap-2">
      <Label htmlFor={id}>{label}</Label>
      <Input
        id={id}
        name={name}
        type={type}
        defaultValue={defaultValue}
        required
      />
    </div>
  );
}
