import { describe, test, expect } from "bun:test";
import jwt from "jsonwebtoken";
import crypto from "crypto";
import { signPermissions } from "../../src/modules/permission-utils/signPermissions";

// The test setup mocks the constants module with a test RSA key pair.
// signPermissions imports permissionsPrivateKey from constants, which
// is the test private key generated in setup.ts. We can verify with the
// corresponding test public key.

// Re-generate the same key pair used in setup.ts from constants mock:
// The mock uses _testPrivateKey/_testPublicKey, but we can decode the JWT
// to verify its contents without needing the public key directly.

describe("signPermissions", () => {
  test("returns a string (JWT)", () => {
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions: ["company.fetch.many"],
    });
    expect(typeof token).toBe("string");
    expect(token.split(".")).toHaveLength(3); // header.payload.signature
  });

  test("JWT payload contains permissions array", () => {
    const permissions = ["company.fetch.many", "credential.read"];
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions,
    });
    const decoded = jwt.decode(token) as any;
    expect(decoded.permissions).toEqual(permissions);
  });

  test("JWT contains issuer claim", () => {
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions: ["*"],
    });
    const decoded = jwt.decode(token, { complete: true }) as any;
    expect(decoded.payload.iss).toBe("optima");
  });

  test("JWT contains subject claim", () => {
    const token = signPermissions({
      issuer: "optima",
      subject: "role-abc",
      permissions: ["*"],
    });
    const decoded = jwt.decode(token, { complete: true }) as any;
    expect(decoded.payload.sub).toBe("role-abc");
  });

  test("JWT uses RS256 algorithm", () => {
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions: [],
    });
    const decoded = jwt.decode(token, { complete: true }) as any;
    expect(decoded.header.alg).toBe("RS256");
  });

  test("handles empty permissions array", () => {
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions: [],
    });
    const decoded = jwt.decode(token) as any;
    expect(decoded.permissions).toEqual([]);
  });

  test("handles large permissions arrays", () => {
    const permsList = Array.from({ length: 100 }, (_, i) => `perm.${i}`);
    const token = signPermissions({
      issuer: "optima",
      subject: "user-1",
      permissions: permsList,
    });
    const decoded = jwt.decode(token) as any;
    expect(decoded.permissions).toHaveLength(100);
    expect(decoded.permissions[0]).toBe("perm.0");
    expect(decoded.permissions[99]).toBe("perm.99");
  });
});
