// Tests du chiffrement des secrets de connecteurs — purs, secret explicite
// (aucune dépendance à l'env).
import { describe, expect, test } from "bun:test";
import {
  decryptSecret,
  decryptSecretOrLegacy,
  encryptSecret,
  isEncryptedSecret,
} from "./crypto";

const SECRET = "test-secret-0123456789abcdef0123456789abcdef";

describe("encryptSecret / decryptSecret", () => {
  test("round-trip", () => {
    const blob = encryptSecret("sk-mangools-token", SECRET);
    expect(decryptSecret(blob, SECRET)).toBe("sk-mangools-token");
  });

  test("format v1:<iv>:<tag>:<ct>", () => {
    const blob = encryptSecret("x", SECRET);
    expect(blob.split(":")).toHaveLength(4);
    expect(blob.startsWith("v1:")).toBe(true);
  });

  test("IV aléatoire — deux chiffrés du même clair diffèrent", () => {
    expect(encryptSecret("same", SECRET)).not.toBe(
      encryptSecret("same", SECRET),
    );
  });

  test("blob altéré → throw connector_secret_invalid", () => {
    const blob = encryptSecret("secret", SECRET);
    const parts = blob.split(":");
    // Altère le ciphertext (dernier segment)
    const tampered = [...parts.slice(0, 3), `A${parts[3].slice(1)}`].join(":");
    expect(() => decryptSecret(tampered, SECRET)).toThrow(
      "connector_secret_invalid",
    );
  });

  test("mauvais secret → throw", () => {
    const blob = encryptSecret("secret", SECRET);
    expect(() => decryptSecret(blob, "autre-secret")).toThrow(
      "connector_secret_invalid",
    );
  });

  test("format inconnu → throw", () => {
    expect(() => decryptSecret("v2:a:b:c", SECRET)).toThrow(
      "connector_secret_invalid",
    );
    expect(() => decryptSecret("plain-text-key", SECRET)).toThrow(
      "connector_secret_invalid",
    );
  });

  test("secret vide → throw connector_secret_missing", () => {
    expect(() => encryptSecret("x", "")).toThrow("connector_secret_missing");
  });
});

describe("decryptSecretOrLegacy", () => {
  test("blob v1 → déchiffré", () => {
    const blob = encryptSecret("tok", SECRET);
    expect(decryptSecretOrLegacy(blob, SECRET)).toBe("tok");
  });

  test("valeur legacy en clair → renvoyée telle quelle", () => {
    expect(decryptSecretOrLegacy("legacy-plaintext-key", SECRET)).toBe(
      "legacy-plaintext-key",
    );
    expect(isEncryptedSecret("legacy-plaintext-key")).toBe(false);
  });
});
