"use server";

import { prisma } from "@/lib/prisma";
import { sendMail } from "@/lib/mail/mailer";
import {
  generateRawToken,
  hashToken,
  RESET_TOKEN_TTL_MS,
} from "@/lib/auth/tokens";
import { hashPassword } from "@/lib/auth/password";
import { requestResetSchema, confirmResetSchema } from "@/lib/validation/auth";

export type ResetState = { error?: string; success?: boolean };

/**
 * Schritt 1: Reset anfordern. Antwortet IMMER mit Erfolg (kein Enumeration),
 * versendet aber nur bei existierendem, aktivem Konto eine Mail.
 */
export async function requestResetAction(
  _prev: ResetState,
  formData: FormData,
): Promise<ResetState> {
  const parsed = requestResetSchema.safeParse({ email: formData.get("email") });
  if (!parsed.success) {
    return { error: "Bitte eine gültige E-Mail-Adresse eingeben." };
  }

  const user = await prisma.user.findUnique({
    where: { email: parsed.data.email },
  });

  if (user && user.status === "ACTIVE") {
    const raw = generateRawToken();
    await prisma.passwordResetToken.create({
      data: {
        userId: user.id,
        tokenHash: hashToken(raw),
        expiresAt: new Date(Date.now() + RESET_TOKEN_TTL_MS),
      },
    });

    const link = `${process.env.APP_URL ?? "http://localhost:3000"}/reset/${raw}`;
    await sendMail({
      to: user.email,
      subject: "Avaria Team OS — Passwort zurücksetzen",
      text: `Setze dein Passwort zurück (gültig 1 Stunde): ${link}`,
      html: `<p>Hallo,</p><p>du kannst dein Passwort über folgenden Link zurücksetzen (gültig 1&nbsp;Stunde):</p><p><a href="${link}">${link}</a></p><p>Falls du das nicht angefordert hast, ignoriere diese E-Mail.</p>`,
    });
  }

  return { success: true };
}

/** Schritt 2: Neues Passwort mit gültigem Token setzen. */
export async function confirmResetAction(
  _prev: ResetState,
  formData: FormData,
): Promise<ResetState> {
  const parsed = confirmResetSchema.safeParse({
    token: formData.get("token"),
    newPassword: formData.get("newPassword"),
    confirmPassword: formData.get("confirmPassword"),
  });

  if (!parsed.success) {
    return { error: parsed.error.issues[0]?.message ?? "Ungültige Eingabe." };
  }

  const record = await prisma.passwordResetToken.findUnique({
    where: { tokenHash: hashToken(parsed.data.token) },
  });

  if (!record || record.usedAt || record.expiresAt < new Date()) {
    return { error: "Der Link ist ungültig oder abgelaufen." };
  }

  const newHash = await hashPassword(parsed.data.newPassword);

  await prisma.$transaction([
    prisma.user.update({
      where: { id: record.userId },
      data: { passwordHash: newHash },
    }),
    prisma.passwordResetToken.update({
      where: { id: record.id },
      data: { usedAt: new Date() },
    }),
    // Alle weiteren offenen Tokens dieses Nutzers entwerten.
    prisma.passwordResetToken.deleteMany({
      where: { userId: record.userId, usedAt: null, id: { not: record.id } },
    }),
    prisma.auditLog.create({
      data: {
        userId: record.userId,
        action: "auth.password_reset",
        entity: "User",
        entityId: record.userId,
      },
    }),
  ]);

  return { success: true };
}
