// billdeskpg/utils/symjose.js
const jose = require("node-jose");

async function encrypt(request, clientId, encryptionKey) {
  console.log("🔒 [Encrypt] Starting...");
  const keystore = jose.JWK.createKeyStore();
  const jwk = {
    kty: "oct",
    k: Buffer.from(encryptionKey).toString('base64'),
    alg: "A256GCM"
  };
  const key = await keystore.add(jwk);
  const input = Buffer.from(request, "utf8");
  const header = {
    alg: "dir",
    enc: "A256GCM",
    clientid: clientId
  };
  const encrypted = await jose.JWE.createEncrypt(
    { format: "compact", fields: header },
    key
  ).update(input).final();
  console.log("📦 [Encrypt] Encrypted JWE:", encrypted);
  return encrypted;
}

async function decrypt(encryptedData, encryptionKey, encryptionKeyId) {
  console.log("🔓 [Decrypt] Starting...");
  const keystore = jose.JWK.createKeyStore();
  const jwk = {
    kty: "oct",
    k: Buffer.from(encryptionKey).toString('base64'),
    alg: "A256GCM",
    kid: encryptionKeyId
  };
  const key = await keystore.add(jwk);
  const jweObject = await jose.JWE.createDecrypt(key).decrypt(encryptedData);
  const decrypted = jweObject.plaintext.toString("utf8");
  console.log("✅ Decrypted JSON:", decrypted);
  return decrypted;
}

async function sign(request, clientId, signingKey) {
  console.log("✍️ [Sign] Starting...");
  const keystore = jose.JWK.createKeyStore();
  const jwk = {
    kty: "oct",
    k: Buffer.from(signingKey).toString('base64'),
    alg: "HS256"
  };
  const key = await keystore.add(jwk);
  const header = { alg: "HS256", clientid: clientId };
  const jwsObject = await jose.JWS.createSign({ format: "compact", fields: header }, key)
    .update(request)
    .final();
  const jwsString = (typeof jwsObject === "string") ? jwsObject : JSON.stringify(jwsObject);
  console.log("✅ [Sign] JWS:", jwsString);
  return jwsString;
}

async function verify(request, signingKey, signingKeyId) {
  console.log("🕵️ [Verify] Starting...");
  const keystore = jose.JWK.createKeyStore();
  const jwk = {
    kty: "oct",
    k: Buffer.from(signingKey).toString('base64'),
    alg: "HS256",
    use: "sig"
  };
  const key = await keystore.add(jwk);
  const verified = await jose.JWS.createVerify(key).verify(request);
  console.log("✅ Signature verified");
  return verified.payload.toString("utf8");
}

// wrappers

async function encryptAndSign(request, clientId, encryptionKey, signingKey) {
  console.log("🔐 [encryptAndSign] Wrapping...");
  const encrypted = await encrypt(request, clientId, encryptionKey);
  const encryptedWithCRLF = encrypted.replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/\n/g, '\r\n');
  const signed = await sign(encryptedWithCRLF, clientId, signingKey);
  return signed;
}

async function verifyAndDecrypt(request, encryptionKey, encryptionKeyId, signingKey, signingKeyId) {
  console.log("🔓 [verifyAndDecrypt] Wrapping...");
  if (!request || request.length === 0 || request[0] === "{") {
    console.log("   ℹ️ Already plain JSON");
    return request;
  }
  const verified = await verify(request, signingKey, signingKeyId);
  const decrypted = await decrypt(verified, encryptionKey, encryptionKeyId);
  console.log("Decrypted: ", decrypted);
  return decrypted;
}

module.exports = {
  encrypt,
  decrypt,
  sign,
  verify,
  encryptAndSign,
  verifyAndDecrypt
};
