import { describe, expect, it } from "bun:test";
import {
  IMPERSONATION_BLOCKED_PATHS,
  isBlockedDuringImpersonation,
} from "./impersonation-blocked-paths";

describe("isBlockedDuringImpersonation", () => {
  it("bloque les écritures de compte", () => {
    for (const p of [
      "/update-user",
      "/change-email",
      "/change-password",
      "/delete-user",
      "/link-social",
      "/unlink-account",
      "/revoke-session",
      "/revoke-sessions",
      "/revoke-other-sessions",
    ]) {
      expect(isBlockedDuringImpersonation(p)).toBe(true);
    }
  });

  it("bloque la délivrance de jetons OAuth du fournisseur", () => {
    // `resolveUserId` privilégie la session sur le `userId` du corps : sous
    // impersonation ces routes rendraient le jeton Google vivant de la CIBLE.
    // Les appelants GSC serveur ne passent pas de headers → session null →
    // garde jamais déclenchée sur eux (la synchro Search Console est intacte).
    for (const p of ["/get-access-token", "/refresh-token"]) {
      expect(isBlockedDuringImpersonation(p)).toBe(true);
    }
  });

  it("bloque les écritures 2FA du plugin twoFactor", () => {
    // Le mot de passe de la cible est aujourd'hui TOUJOURS exigé sur ces routes
    // (`shouldRequirePassword` renvoie `true` tant que `allowPasswordless` n'est
    // pas configuré, ce que ce projet ne fait pas). On bloque quand même : une
    // bascule de 2FA sous impersonation ne laisse aucune trace d'audit, et le
    // rempart mot de passe tomberait si `allowPasswordless` était activé un jour.
    for (const p of [
      "/two-factor/enable",
      "/two-factor/disable",
      "/two-factor/generate-backup-codes",
      "/two-factor/get-totp-uri",
    ]) {
      expect(isBlockedDuringImpersonation(p)).toBe(true);
    }
  });

  it("laisse SORTIR de l'impersonation", () => {
    // Sans ça, l'opérateur reste enfermé dans la session de la cible.
    expect(isBlockedDuringImpersonation("/admin/stop-impersonating")).toBe(
      false,
    );
  });

  it("ne bloque pas la lecture de session ni la déconnexion", () => {
    expect(isBlockedDuringImpersonation("/get-session")).toBe(false);
    expect(isBlockedDuringImpersonation("/sign-out")).toBe(false);
  });

  it("compare en correspondance exacte, jamais par préfixe", () => {
    // Un préfixe attraperait /admin/stop-impersonating au passage.
    expect(isBlockedDuringImpersonation("/update-user-preferences")).toBe(
      false,
    );
    expect(isBlockedDuringImpersonation("/admin/update-user")).toBe(false);
    expect(isBlockedDuringImpersonation("/two-factor/verify-totp")).toBe(false);
    expect(isBlockedDuringImpersonation("")).toBe(false);
  });

  it("n'inclut aucun chemin sous /admin/", () => {
    for (const p of IMPERSONATION_BLOCKED_PATHS) {
      expect(p.startsWith("/admin/")).toBe(false);
    }
  });

  it("n'expose que des chemins absolus", () => {
    for (const p of IMPERSONATION_BLOCKED_PATHS) {
      expect(p.startsWith("/")).toBe(true);
    }
  });
});
