import { createPrivateKey, randomUUID as cryptoRandomUUID, sign as signBytes } from "node:crypto";

const AUDIENCE = "code-remote-manager-backend";
const PRODUCT_ID = "pro_multi_account";
const MAX_ACCOUNTS = 5;
const CERTIFICATE_LIFETIME_SECONDS = 30 * 24 * 60 * 60;
const BINDING = /^[A-Za-z0-9_-]{43}$/;
const KEY_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;

export function createEntitlementSigner({
  privateKey,
  keyId,
  issuer,
  now = Date.now,
  randomUUID = cryptoRandomUUID,
}) {
  let signingKey;
  try {
    if (!(typeof privateKey === "string" || Buffer.isBuffer(privateKey))) throw new Error();
    if (!KEY_ID.test(keyId ?? "") || !validIssuer(issuer) || typeof now !== "function" || typeof randomUUID !== "function") throw new Error();
    signingKey = createPrivateKey(privateKey);
    if (signingKey.asymmetricKeyType !== "ed25519") throw new Error();
  } catch {
    throw signingError("invalid_signing_config", "Entitlement signing configuration is invalid.");
  }

  return {
    sign({ backendKeyThumbprint, challengeHash } = {}) {
      if (!BINDING.test(backendKeyThumbprint ?? "") || !BINDING.test(challengeHash ?? "")) {
        throw signingError("invalid_entitlement_binding", "The entitlement binding is invalid.");
      }
      const milliseconds = Number(now());
      const jti = randomUUID();
      if (!Number.isFinite(milliseconds) || typeof jti !== "string" || jti.length === 0) {
        throw signingError("entitlement_signing_unavailable", "Entitlement signing is unavailable.");
      }
      const iat = Math.floor(milliseconds / 1000);
      const exp = iat + CERTIFICATE_LIFETIME_SECONDS;
      const header = { alg: "EdDSA", kid: keyId };
      const claims = {
        iss: issuer,
        aud: AUDIENCE,
        productId: PRODUCT_ID,
        maxAccounts: MAX_ACCOUNTS,
        backendKeyThumbprint,
        challengeHash,
        iat,
        exp,
        jti,
      };
      const signingInput = `${encode(header)}.${encode(claims)}`;
      try {
        const signature = signBytes(null, Buffer.from(signingInput), signingKey).toString("base64url");
        return {
          certificate: `${signingInput}.${signature}`,
          expiresAt: new Date(exp * 1000).toISOString(),
        };
      } catch {
        throw signingError("entitlement_signing_unavailable", "Entitlement signing is unavailable.");
      }
    },
  };
}

function validIssuer(value) {
  try {
    const parsed = new URL(value);
    return parsed.protocol === "https:"
      && !parsed.username
      && !parsed.password
      && !parsed.search
      && !parsed.hash
      && parsed.pathname === "/"
      && parsed.origin === value;
  } catch {
    return false;
  }
}

function encode(value) {
  return Buffer.from(JSON.stringify(value)).toString("base64url");
}

function signingError(code, message) {
  const error = new Error(message);
  error.code = code;
  error.status = 500;
  return error;
}
