"use server";

import { revalidatePath } from "next/cache";
import { z } from "zod";

import { requireKitaSession } from "@/lib/auth-utils";
import { prisma } from "@/lib/prisma";

// Telefonnummern: führendes "+" optional, dann Ziffern, Leerzeichen, Bindestriche,
// Klammern oder Schrägstriche. Mindestens 6 Ziffern damit es plausibel ist.
// Schließt damit "abc-123-not-a-phone" aus, lässt aber internationale Formate zu.
const phonePattern = /^[+]?[0-9][\d\s\-()/.]{4,}$/;

// PLZ: Ziffern/Buchstaben/Leerzeichen/Bindestriche, 3–10 Zeichen.
// Kein striktes DE-Format (5 Ziffern), damit auch AT/CH/UK denkbar sind.
const postalCodePattern = /^[0-9A-Za-z][0-9A-Za-z\s-]{2,9}$/;

const childSchema = z
  .object({
    firstName: z.string().min(1, "Vorname ist erforderlich.").max(100).trim(),
    lastName: z.string().min(1, "Nachname ist erforderlich.").max(100).trim(),
    dateOfBirth: z.string().optional(),
  })
  .superRefine((data, ctx) => {
    if (!data.dateOfBirth) return;
    const parsed = new Date(`${data.dateOfBirth}T00:00:00`);
    if (Number.isNaN(parsed.getTime())) {
      ctx.addIssue({
        path: ["dateOfBirth"],
        code: "custom",
        message: "Bitte ein gültiges Datum angeben.",
      });
      return;
    }
    // In der Zukunft geborene Kinder existieren nicht.
    const today = new Date();
    today.setHours(23, 59, 59, 999);
    if (parsed > today) {
      ctx.addIssue({
        path: ["dateOfBirth"],
        code: "custom",
        message: "Geburtsdatum darf nicht in der Zukunft liegen.",
      });
    }
    // Schutz vor offensichtlichen Tippfehlern (1899 statt 1989 o.ä.).
    if (parsed.getFullYear() < 1900) {
      ctx.addIssue({
        path: ["dateOfBirth"],
        code: "custom",
        message: "Bitte ein realistisches Geburtsdatum angeben.",
      });
    }
  });

const familySchema = z.object({
  familyName: z.string().min(1, "Familienname ist erforderlich.").max(120).trim(),
});

const contactSchema = z.object({
  phone: z
    .string()
    .trim()
    .max(50)
    .optional()
    .refine(
      (v) => !v || phonePattern.test(v),
      "Bitte eine gültige Telefonnummer angeben.",
    ),
  street: z.string().trim().max(120).optional(),
  postalCode: z
    .string()
    .trim()
    .max(20)
    .optional()
    .refine(
      (v) => !v || postalCodePattern.test(v),
      "Bitte eine gültige Postleitzahl angeben.",
    ),
  city: z.string().trim().max(100).optional(),
});

function parseDateInput(value?: string) {
  if (!value) return null;

  const date = new Date(`${value}T00:00:00`);
  return Number.isNaN(date.getTime()) ? null : date;
}

// Gibt die erste konkrete Field-Error-Message aus einem Zod-Fehler zurück,
// damit der User nicht nur "Ungültige Eingabedaten" sieht.
function firstZodMessage(
  error: z.ZodError,
  fallback: string,
): string {
  const issue = error.issues[0];
  return issue?.message || fallback;
}

async function requireOwnFamilyChild(
  childId: string,
  familyId: string | null,
  kitaId: string,
) {
  if (!familyId) return null;

  return prisma.child.findFirst({
    where: { id: childId, familyId, kitaId },
  });
}

export async function createMyChild(rawPayload: unknown) {
  const session = await requireKitaSession();
  const parsed = childSchema.safeParse(rawPayload);

  if (!session.user.familyId) {
    return { error: "Dein Account ist noch keinem Haushalt zugeordnet." };
  }

  if (!parsed.success) {
    return { error: firstZodMessage(parsed.error, "Ungültige Eingabedaten.") };
  }

  try {
    await prisma.child.create({
      data: {
        kitaId: session.user.kitaId,
        familyId: session.user.familyId,
        firstName: parsed.data.firstName,
        lastName: parsed.data.lastName,
        dateOfBirth: parseDateInput(parsed.data.dateOfBirth),
      },
    });

    revalidatePath("/dashboard/profil");
    revalidatePath("/dashboard/families");
    return { success: true };
  } catch (error) {
    console.error("Fehler beim Anlegen des Kindes:", error);
    return { error: "Das Kind konnte nicht angelegt werden." };
  }
}

export async function createMyFamily(rawPayload: unknown) {
  const session = await requireKitaSession();
  const parsed = familySchema.safeParse(rawPayload);

  if (!parsed.success) {
    return { error: "Bitte gib einen gültigen Familiennamen ein." };
  }

  if (session.user.familyId) {
    return { error: "Dein Account ist bereits einem Haushalt zugeordnet." };
  }

  try {
    await prisma.$transaction(async (tx) => {
      const family = await tx.family.create({
        data: {
          kitaId: session.user.kitaId,
          name: parsed.data.familyName,
        },
      });

      await tx.user.update({
        where: { id: session.user.id },
        data: { familyId: family.id },
      });
    });

    revalidatePath("/dashboard/profil");
    revalidatePath("/dashboard/families");
    revalidatePath("/dashboard/adressbuch");
    revalidatePath("/dashboard");
    return { success: true };
  } catch (error) {
    console.error("Fehler beim Anlegen des eigenen Haushalts:", error);
    return { error: "Der Haushalt konnte nicht angelegt werden." };
  }
}

export async function updateMyContact(rawPayload: unknown) {
  const session = await requireKitaSession();
  const parsed = contactSchema.safeParse(rawPayload);

  if (!parsed.success) {
    return { error: firstZodMessage(parsed.error, "Ungültige Kontaktdaten.") };
  }

  try {
    await prisma.user.update({
      where: { id: session.user.id },
      data: {
        phone: parsed.data.phone || null,
        street: parsed.data.street || null,
        postalCode: parsed.data.postalCode || null,
        city: parsed.data.city || null,
      },
    });

    revalidatePath("/dashboard/profil");
    revalidatePath("/dashboard");
    revalidatePath("/dashboard/adressbuch");
    return { success: true };
  } catch (error) {
    console.error("Fehler beim Aktualisieren der Kontaktdaten:", error);
    return { error: "Kontaktdaten konnten nicht gespeichert werden." };
  }
}

export async function updateMyChild(childId: string, rawPayload: unknown) {
  const session = await requireKitaSession();
  const parsed = childSchema.safeParse(rawPayload);

  if (!parsed.success) {
    return { error: firstZodMessage(parsed.error, "Ungültige Eingabedaten.") };
  }

  try {
    const child = await requireOwnFamilyChild(
      childId,
      session.user.familyId,
      session.user.kitaId,
    );

    if (!child) {
      return { error: "Dieses Kind gehört nicht zu deinem Haushalt." };
    }

    await prisma.child.update({
      where: { id: childId },
      data: {
        firstName: parsed.data.firstName,
        lastName: parsed.data.lastName,
        dateOfBirth: parseDateInput(parsed.data.dateOfBirth),
      },
    });

    revalidatePath("/dashboard/profil");
    revalidatePath("/dashboard/families");
    return { success: true };
  } catch (error) {
    console.error("Fehler beim Aktualisieren des Kindes:", error);
    return { error: "Das Kind konnte nicht aktualisiert werden." };
  }
}

export async function deleteMyChild(childId: string) {
  const session = await requireKitaSession();

  try {
    const child = await requireOwnFamilyChild(
      childId,
      session.user.familyId,
      session.user.kitaId,
    );

    if (!child) {
      return { error: "Dieses Kind gehört nicht zu deinem Haushalt." };
    }

    await prisma.child.delete({
      where: { id: childId },
    });

    revalidatePath("/dashboard/profil");
    revalidatePath("/dashboard/families");
    return { success: true };
  } catch (error) {
    console.error("Fehler beim Entfernen des Kindes:", error);
    return { error: "Das Kind konnte nicht entfernt werden." };
  }
}

export async function deleteMyAccount() {
  const session = await requireKitaSession();
  
  try {
    const user = await prisma.user.findFirst({
      where: {
        id: session.user.id,
        kitaId: session.user.kitaId,
      },
      select: {
        id: true,
        familyId: true,
      },
    });

    if (!user) {
      return { error: "Account wurde nicht gefunden." };
    }

    if (!user.familyId) {
      await prisma.user.delete({
        where: { id: user.id },
      });
      return { success: true };
    }

    const family = await prisma.family.findFirst({
      where: {
        id: user.familyId,
        kitaId: session.user.kitaId,
      },
      select: {
        id: true,
        users: {
          select: { id: true },
        },
      },
    });

    if (!family) {
      return { error: "Haushalt wurde nicht gefunden." };
    }

    if (family.users.length <= 1) {
      await prisma.family.delete({
        where: { id: family.id },
      });
      return { success: true };
    }

    await prisma.user.delete({
      where: { id: user.id },
    });

    return { success: true };
  } catch (error) {
    console.error("Fehler beim Löschen des Accounts:", error);
    return { error: "Ein Fehler ist beim Löschen aufgetreten." };
  }
}
