// Verification serveur des tokens Cloudflare Turnstile (challenge anti-bot).
//
// Le widget client appelle la rendu Turnstile qui populate un champ
// `cf-turnstile-response` dans le form. Cote serveur, on POST ce token a
// l'endpoint siteverify de Cloudflare pour confirmer qu'il est valide.
//
// Documentation : https://developers.cloudflare.com/turnstile/get-started/server-side-validation/

import "server-only";

const SITEVERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify";

export type TurnstileResult =
  | { ok: true }
  | { ok: false; reason: "missing_secret" | "missing_token" | "invalid_token" | "network_error" };

/**
 * Verifie un token Turnstile. Retourne ok: true si le token est valide,
 * sinon une raison typee.
 *
 * Si TURNSTILE_SECRET_KEY n'est pas configure, retourne ok: true automatiquement
 * (degradation gracieuse pour dev local sans Cloudflare). En prod, il FAUT
 * configurer la cle ou la verification ne fait rien.
 */
export async function verifyTurnstileToken(
  token: string | null | undefined,
  remoteIp?: string,
): Promise<TurnstileResult> {
  const secret = process.env.TURNSTILE_SECRET_KEY;

  // Pas de cle configuree : degradation gracieuse (dev local), on laisse passer.
  // En prod, ce path est anormal et on devrait logger une fois.
  if (!secret) {
    if (process.env.NODE_ENV === "production") {
      console.warn("[turnstile] TURNSTILE_SECRET_KEY not set, skipping verification");
    }
    return { ok: true };
  }

  if (!token || typeof token !== "string" || token.length === 0) {
    return { ok: false, reason: "missing_token" };
  }

  const body = new URLSearchParams();
  body.append("secret", secret);
  body.append("response", token);
  if (remoteIp) body.append("remoteip", remoteIp);

  try {
    const res = await fetch(SITEVERIFY_URL, {
      method: "POST",
      body,
      headers: { "content-type": "application/x-www-form-urlencoded" },
      // Pas de cache : un token est single-use.
      cache: "no-store",
    });
    if (!res.ok) {
      console.error("[turnstile] siteverify HTTP", res.status);
      return { ok: false, reason: "network_error" };
    }
    const data = (await res.json()) as { success: boolean; "error-codes"?: string[] };
    if (!data.success) {
      console.warn("[turnstile] verify failed:", data["error-codes"]);
      return { ok: false, reason: "invalid_token" };
    }
    return { ok: true };
  } catch (err) {
    console.error("[turnstile] verify error:", err);
    return { ok: false, reason: "network_error" };
  }
}
