"use server";

import { revalidatePath } from "next/cache";
import { AuditTargetType, UserRole } from "@prisma/client";
import { z } from "zod";

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

const deleteKitaSchema = z.object({
  kitaId: z.string().min(1),
  confirmationName: z.string().min(1).trim(),
});

const deleteUserSchema = z.object({
  userId: z.string().min(1),
  confirmationEmail: z.string().email().toLowerCase().trim(),
});

const userIdSchema = z.string().min(1);

type ActionResult = {
  ok: boolean;
  error?: string;
};

async function requireSuperadminActor() {
  const session = await requireRole([UserRole.SUPERADMIN]);
  return {
    id: session.user.id,
    email: session.user.email ?? session.user.name ?? "Unbekannter Superadmin",
  };
}

async function getKitaDeleteCounts(kitaId: string) {
  const [
    users,
    families,
    children,
    termine,
    absences,
    announcements,
    invitations,
    eventParticipations,
  ] = await Promise.all([
    prisma.user.count({ where: { kitaId } }),
    prisma.family.count({ where: { kitaId } }),
    prisma.child.count({ where: { kitaId } }),
    prisma.termin.count({ where: { kitaId } }),
    prisma.absence.count({ where: { kitaId } }),
    prisma.announcement.count({ where: { kitaId } }),
    prisma.invitation.count({ where: { kitaId } }),
    prisma.eventParticipation.count({ where: { kitaId } }),
  ]);

  return {
    users,
    families,
    children,
    termine,
    absences,
    announcements,
    invitations,
    eventParticipations,
  };
}

export async function deleteKita(
  rawPayload: unknown,
): Promise<ActionResult & { redirectTo?: string }> {
  const actor = await requireSuperadminActor();
  const parsed = deleteKitaSchema.safeParse(rawPayload);
  if (!parsed.success) {
    return { ok: false, error: "Ungültige Eingabedaten." };
  }

  const kita = await prisma.kita.findUnique({
    where: { id: parsed.data.kitaId },
    select: { id: true, name: true, slug: true },
  });

  if (!kita) {
    return { ok: false, error: "Kita wurde nicht gefunden." };
  }

  if (parsed.data.confirmationName !== kita.name) {
    return {
      ok: false,
      error: "Die Bestätigung muss exakt dem Kita-Namen entsprechen.",
    };
  }

  const counts = await getKitaDeleteCounts(kita.id);

  await prisma.$transaction(async (tx) => {
    await tx.auditLog.create({
      data: {
        actorUserId: actor.id,
        actorEmail: actor.email,
        action: "KITA_DELETE",
        targetType: AuditTargetType.KITA,
        targetId: kita.id,
        targetLabel: `${kita.name} (${kita.slug})`,
        targetKitaId: kita.id,
        metadata: counts,
      },
    });

    await tx.kita.delete({ where: { id: kita.id } });
  });

  revalidatePath("/admin");
  revalidatePath("/admin/audit");
  return { ok: true, redirectTo: "/admin" };
}

async function findMutableTenantUser(userId: string, actorId: string) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: {
      id: true,
      email: true,
      firstName: true,
      lastName: true,
      role: true,
      kitaId: true,
      familyId: true,
      failedLoginAttempts: true,
      lockedUntil: true,
      kita: {
        select: {
          name: true,
          slug: true,
        },
      },
      family: {
        select: {
          name: true,
          _count: {
            select: {
              users: true,
            },
          },
        },
      },
    },
  });

  if (!user) {
    return { error: "Benutzer wurde nicht gefunden." } as const;
  }
  if (user.id === actorId) {
    return { error: "Das eigene Superadmin-Konto kann hier nicht geändert werden." } as const;
  }
  if (user.role === UserRole.SUPERADMIN) {
    return { error: "Andere Superadmins werden in V1 nicht verwaltet." } as const;
  }
  if (!user.kitaId) {
    return { error: "Nur tenant-gebundene Benutzer können verwaltet werden." } as const;
  }

  return { user } as const;
}

export async function deleteUser(rawPayload: unknown): Promise<ActionResult> {
  const actor = await requireSuperadminActor();
  const parsed = deleteUserSchema.safeParse(rawPayload);
  if (!parsed.success) {
    return { ok: false, error: "Ungültige Eingabedaten." };
  }

  const lookup = await findMutableTenantUser(parsed.data.userId, actor.id);
  if ("error" in lookup) {
    return { ok: false, error: lookup.error };
  }

  const { user } = lookup;
  if (parsed.data.confirmationEmail !== user.email) {
    return {
      ok: false,
      error: "Die Bestätigung muss exakt der Benutzer-E-Mail entsprechen.",
    };
  }

  await prisma.$transaction(async (tx) => {
    await tx.verificationToken.deleteMany({
      where: { identifier: user.id },
    });
    await tx.auditLog.create({
      data: {
        actorUserId: actor.id,
        actorEmail: actor.email,
        action: "USER_DELETE",
        targetType: AuditTargetType.USER,
        targetId: user.id,
        targetLabel: `${user.firstName} ${user.lastName} <${user.email}>`,
        targetKitaId: user.kitaId,
        metadata: {
          role: user.role,
          kitaName: user.kita?.name ?? null,
          kitaSlug: user.kita?.slug ?? null,
          familyId: user.familyId,
          familyName: user.family?.name ?? null,
          familyUserCountBeforeDelete: user.family?._count.users ?? null,
        },
      },
    });
    await tx.user.delete({ where: { id: user.id } });
  });

  revalidatePath("/admin");
  revalidatePath(`/admin/kitas/${user.kitaId}`);
  revalidatePath("/admin/audit");
  return { ok: true };
}

async function updateUserSupportState(
  userId: string,
  action: "USER_LOCK" | "USER_UNLOCK" | "USER_FAILED_LOGIN_RESET",
  data: {
    lockedUntil?: Date | null;
    failedLoginAttempts?: number;
  },
): Promise<ActionResult> {
  const actor = await requireSuperadminActor();
  const parsed = userIdSchema.safeParse(userId);
  if (!parsed.success) {
    return { ok: false, error: "Ungültige Eingabedaten." };
  }

  const lookup = await findMutableTenantUser(parsed.data, actor.id);
  if ("error" in lookup) {
    return { ok: false, error: lookup.error };
  }

  const { user } = lookup;

  await prisma.$transaction(async (tx) => {
    await tx.user.update({
      where: { id: user.id },
      data,
    });
    await tx.auditLog.create({
      data: {
        actorUserId: actor.id,
        actorEmail: actor.email,
        action,
        targetType: AuditTargetType.USER,
        targetId: user.id,
        targetLabel: `${user.firstName} ${user.lastName} <${user.email}>`,
        targetKitaId: user.kitaId,
        metadata: {
          role: user.role,
          previousLockedUntil: user.lockedUntil?.toISOString() ?? null,
          previousFailedLoginAttempts: user.failedLoginAttempts,
        },
      },
    });
  });

  revalidatePath("/admin");
  revalidatePath(`/admin/kitas/${user.kitaId}`);
  revalidatePath("/admin/audit");
  return { ok: true };
}

export async function lockUser(userId: string): Promise<ActionResult> {
  return updateUserSupportState(userId, "USER_LOCK", {
    lockedUntil: new Date("2099-12-31T23:59:59.000Z"),
  });
}

export async function unlockUser(userId: string): Promise<ActionResult> {
  return updateUserSupportState(userId, "USER_UNLOCK", {
    lockedUntil: null,
    failedLoginAttempts: 0,
  });
}

export async function resetFailedLoginAttempts(
  userId: string,
): Promise<ActionResult> {
  return updateUserSupportState(userId, "USER_FAILED_LOGIN_RESET", {
    failedLoginAttempts: 0,
  });
}

