// src/lib/account/password-actions.ts
"use server";

import { headers } from "next/headers";
import { auth } from "@/lib/auth";
import { sessionIsImpersonated } from "@/lib/auth/impersonation-guard";
import { validatePassword } from "@/lib/auth/password-policy";

/**
 * Définit un PREMIER mot de passe pour un compte né sans credential (magic
 * link / social). Le endpoint server-only `setPassword` de better-auth porte
 * lui-même le garde-fou : il refuse (PASSWORD_ALREADY_SET) si un credential
 * existe déjà — impossible de contourner le flow « changer » qui exige
 * l'ancien mot de passe.
 */
export async function setInitialPasswordAction(
  newPassword: string,
): Promise<{ ok: true } | { ok: false; error: string }> {
  const reqHeaders = await headers();
  // Lecture AUTORITAIRE obligatoire : `setPassword` passe par
  // `sensitiveSessionMiddleware`, qui jette la mémoïsation et relit la session
  // en base. Sans `disableCookieCache` la garde ci-dessous lirait le cookie
  // `session_data` (valide 5 min) pendant que l'écriture, elle, résout la vraie
  // session — un opérateur rejouant son cookie d'avant l'impersonation avec le
  // `session_token` impersonné passerait la garde et poserait quand même le mot
  // de passe sur le compte de la cible. Les deux lectures doivent voir la même
  // session.
  const session = await auth.api.getSession({
    headers: reqHeaders,
    query: { disableCookieCache: true },
  });
  if (!session?.user?.id) return { ok: false, error: "not-authenticated" };
  // Pendant une impersonation, `session.user` EST la cible : on poserait un mot
  // de passe permanent sur son compte, et sans trace d'audit (les gardes SYS
  // renvoient faux pendant l'impersonation, `recordAdminAction` n'est jamais
  // atteint). Blocage dur, pas un skip silencieux.
  if (sessionIsImpersonated(session)) {
    return { ok: false, error: "impersonation-forbidden" };
  }
  // Même politique forte qu'au signup (le endpoint ne vérifie que la longueur).
  const policy = validatePassword(newPassword);
  if (!policy.ok) return { ok: false, error: "weak-password" };
  try {
    await auth.api.setPassword({
      headers: reqHeaders,
      body: { newPassword },
    });
    return { ok: true };
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    if (/already/i.test(message)) {
      return { ok: false, error: "already-set" };
    }
    console.error("[account] setInitialPasswordAction failed:", err);
    return { ok: false, error: "unknown" };
  }
}
