import assert from "node:assert/strict";
import { generateKeyPairSync, verify } from "node:crypto";
import test from "node:test";

import { createEntitlementSigner } from "./entitlement-signer.js";

const NOW = Date.UTC(2026, 7, 2, 12, 0, 0);
const THUMBPRINT = "a".repeat(43);
const CHALLENGE_HASH = "b".repeat(43);

test("signer issues a 30-day backend-bound Ed25519 compact certificate", () => {
  const { privateKey, publicKey } = generateKeyPairSync("ed25519");
  const privatePem = privateKey.export({ format: "pem", type: "pkcs8" });
  const signer = createEntitlementSigner({
    privateKey: privatePem,
    keyId: "release-2026-01",
    issuer: "https://entitlements.example.com",
    now: () => NOW,
    randomUUID: () => "11111111-2222-4333-8444-555555555555",
  });

  const result = signer.sign({
    backendKeyThumbprint: THUMBPRINT,
    challengeHash: CHALLENGE_HASH,
  });
  const [encodedHeader, encodedClaims, encodedSignature] = result.certificate.split(".");
  assert.deepEqual(decode(encodedHeader), { alg: "EdDSA", kid: "release-2026-01" });
  assert.deepEqual(decode(encodedClaims), {
    iss: "https://entitlements.example.com",
    aud: "code-remote-manager-backend",
    productId: "pro_multi_account",
    maxAccounts: 5,
    backendKeyThumbprint: THUMBPRINT,
    challengeHash: CHALLENGE_HASH,
    iat: 1785672000,
    exp: 1788264000,
    jti: "11111111-2222-4333-8444-555555555555",
  });
  assert.equal(
    verify(null, Buffer.from(`${encodedHeader}.${encodedClaims}`), publicKey, Buffer.from(encodedSignature, "base64url")),
    true
  );
  assert.deepEqual(result, {
    certificate: result.certificate,
    expiresAt: "2026-09-01T12:00:00.000Z",
  });
  assert.equal(JSON.stringify(signer).includes(privatePem.toString()), false);
});

test("signer accepts only mounted Ed25519 PEM value and safe release metadata", async (t) => {
  const ed25519 = generateKeyPairSync("ed25519").privateKey.export({ format: "pem", type: "pkcs8" });
  const rsa = generateKeyPairSync("rsa", { modulusLength: 2048 }).privateKey.export({ format: "pem", type: "pkcs8" });
  const cases = [
    ["path instead of value", "C:\\secrets\\signing-key.pem", "release-2026-01", "https://entitlements.example.com"],
    ["wrong key type", rsa, "release-2026-01", "https://entitlements.example.com"],
    ["unsafe key id", ed25519, "../../secret", "https://entitlements.example.com"],
    ["non-HTTPS issuer", ed25519, "crm-entitlement-verifier", "crm-entitlement-verifier"],
  ];
  for (const [name, privateKey, keyId, issuer] of cases) {
    await t.test(name, () => {
      assert.throws(
        () => createEntitlementSigner({ privateKey, keyId, issuer }),
        (error) => error?.code === "invalid_signing_config" && !JSON.stringify(error).includes(String(privateKey))
      );
    });
  }
});

test("signer rejects malformed binding claims before using the private key", () => {
  const privateKey = generateKeyPairSync("ed25519").privateKey.export({ format: "pem", type: "pkcs8" });
  const signer = createEntitlementSigner({
    privateKey,
    keyId: "release-2026-01",
    issuer: "https://entitlements.example.com",
    now: () => NOW,
  });
  assert.throws(
    () => signer.sign({ backendKeyThumbprint: "short", challengeHash: CHALLENGE_HASH }),
    (error) => error?.code === "invalid_entitlement_binding"
  );
  assert.throws(
    () => signer.sign({ backendKeyThumbprint: THUMBPRINT, challengeHash: "not/base64" }),
    (error) => error?.code === "invalid_entitlement_binding"
  );
});

function decode(value) {
  return JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
}
