"use server";

import { hash } from "bcryptjs";
import { Prisma, UserRole } from "@prisma/client";
import { z } from "zod";

import { signIn } from "@/auth";
import { prisma } from "@/lib/prisma";

// =====================================================================
// /register · Server Action
// ---------------------------------------------------------------------
// Legt einen "heimatlosen" Admin-Account an (kitaId === null) und loggt
// ihn direkt ein. Die Tenant-Erstellung folgt im Onboarding-Wizard.
// =====================================================================

const registerSchema = z.object({
  email: z.string().email("Bitte eine gültige E-Mail-Adresse angeben.").toLowerCase().trim(),
  // bcrypt akzeptiert max. 72 Bytes — wir capen davor zur Sicherheit
  password: z
    .string()
    .min(8, "Mindestens 8 Zeichen.")
    .max(72, "Maximal 72 Zeichen."),
  firstName: z.string().min(1, "Pflichtfeld.").max(100).trim(),
  lastName: z.string().min(1, "Pflichtfeld.").max(100).trim(),
  // HTML-Checkboxen senden "on" wenn aktiviert, sonst nichts
  acceptPrivacyPolicy: z.literal("on", {
    error: "Bitte Datenschutzerklärung akzeptieren.",
  }),
});

const PRIVACY_POLICY_VERSION = "2026-05-01";

export type RegisterState = {
  // Bumped after every action call so the client can key uncontrolled inputs
  // and force a remount with the echoed values from a failed submit.
  attempt: number;
  // Echoed inputs (sans password) so failed submits don't wipe the form.
  values?: {
    firstName?: string;
    lastName?: string;
    email?: string;
    acceptPrivacyPolicy?: boolean;
  };
  errors?: {
    email?: string[];
    password?: string[];
    firstName?: string[];
    lastName?: string[];
    acceptPrivacyPolicy?: string[];
    _form?: string[];
  };
};

function echoValues(formData: FormData): RegisterState["values"] {
  return {
    firstName: String(formData.get("firstName") ?? ""),
    lastName: String(formData.get("lastName") ?? ""),
    email: String(formData.get("email") ?? ""),
    acceptPrivacyPolicy: formData.get("acceptPrivacyPolicy") === "on",
  };
}

export async function registerAction(
  prevState: RegisterState,
  formData: FormData,
): Promise<RegisterState> {
  const attempt = prevState.attempt + 1;
  const parsed = registerSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) {
    return {
      attempt,
      values: echoValues(formData),
      errors: parsed.error.flatten().fieldErrors,
    };
  }
  const { email, password, firstName, lastName } = parsed.data;

  const passwordHash = await hash(password, 12);
  const now = new Date();

  try {
    await prisma.user.create({
      data: {
        email,
        passwordHash,
        firstName,
        lastName,
        // Gründer wird "heimatloser" Admin — beim Onboarding-Abschluss
        // wird die Rolle bestätigt und der User mit einer Kita verknüpft.
        role: UserRole.ADMIN,
        kitaId: null,
        privacyPolicyAcceptedAt: now,
        privacyPolicyVersion: PRIVACY_POLICY_VERSION,
        emailVerifiedAt: now,
      },
    });
  } catch (err) {
    if (
      err instanceof Prisma.PrismaClientKnownRequestError &&
      err.code === "P2002"
    ) {
      return {
        attempt,
        values: echoValues(formData),
        errors: {
          email: ["Mit dieser E-Mail-Adresse existiert bereits ein Account."],
        },
      };
    }
    throw err;
  }

  // Direkt einloggen → wirft NEXT_REDIRECT, das wir nicht abfangen.
  await signIn("credentials", {
    email,
    password,
    redirectTo: "/onboarding",
  });

  // Unreachable – signIn redirected.
  return { attempt };
}
