// services/bbpsIntegrationService.js
const httpClient = require("../utils/httpClient");
const { processRequest } = require("../utils/apirequestmodule");
const { getBBPSConfig } = require("../utils/config");
const { encryptAndSign, verifyAndDecrypt } = require("../utils/symjose");
const { processResponse } = require("../utils/apiresponsemodule");

/**
 * Handles encryption, POST to BBPS, and decryption
 */
async function sendToBBPS({ path, payload, lineEndings = "preserve" }) {
  const config = getBBPSConfig();
  const { baseUrl, clientId, encKey, sigKey, sourceId } = config;
  const url = `${baseUrl}/${sourceId}/${path}`;

  const { headers: builtHeaders, body: plaintext, traceId } = processRequest(payload, { lineEndings });

  let joseEnvelope;
  try {
    joseEnvelope = await encryptAndSign(plaintext, clientId, encKey, sigKey);
  } catch (err) {
    // fallback for split 64-char key
    if (sigKey && sigKey.length === 64) {
      try {
        joseEnvelope = await encryptAndSign(plaintext, clientId, encKey, sigKey.substring(0, 32));
      } catch (_) {
        joseEnvelope = await encryptAndSign(plaintext, clientId, encKey, sigKey.substring(32, 64));
      }
    } else {
      return { success: false, code: 5001, message: "Encryption/signing failed", details: err.message, traceId };
    }
  }

  const headers = { ...builtHeaders, "Content-Type": "application/jose" };
  const resp = await httpClient.post(url, joseEnvelope, { headers });

  if (!resp.ok) {
    if (typeof resp.data === "string" && resp.data.includes(".")) {
      try {
        const decryptedErr = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
        const parsed = JSON.parse(decryptedErr);
        return { success: false, code: resp.status, message: "BBPS returned error", details: parsed, traceId };
      } catch {
        return { success: false, code: resp.status, message: "BBPS returned unreadable error", details: resp.data, traceId };
      }
    }
    return { success: false, code: resp.status || 5020, message: "BBPS returned non-200", details: resp.data || resp.error, traceId };
  }

  try {
    const decrypted = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
    const finalJson = processResponse(decrypted);
    return { success: true, data: finalJson, traceId };
  } catch (err) {
    return { success: false, code: 5002, message: "Failed to decrypt/parse BBPS response", details: err.message, traceId };
  }
}

module.exports = { sendToBBPS };
