// const axios = require('axios');
// const { buildRequest } = require('./requestUtils');
// const { encryptAndSign, verifyAndDecrypt } = require('./symjose');
// const { processResponse } = require('./apiresponsemodule');

// async function encryptAndSignWithFallback(plaintext, clientId, encKey, sigKey) {
//   try {
//     return await encryptAndSign(plaintext, clientId, encKey, sigKey);
//   } catch (err) {
//     // Optional fallback for 64-char keys
//     if (sigKey && sigKey.length === 64) {
//       try {
//         const first = sigKey.substring(0, 32);
//         return await encryptAndSign(plaintext, clientId, encKey, first);
//       } catch (_) {
//         const last = sigKey.substring(32, 64);
//         return await encryptAndSign(plaintext, clientId, encKey, last);
//       }
//     }
//     throw err;
//   }
// }

// /**
//  * Call a BBPS endpoint.
//  * @param {Object} opts
//  * @param {string} opts.path - path relative to /{sourceId}/
//  * @param {string|object} opts.payload - rawBody string (recommended) or object
//  * @param {Object} opts.config - { baseUrl, clientId, encKey, sigKey, sourceId }
//  * @param {('preserve'|'lf'|'crlf')} opts.lineEndings - how to normalize body before JWE
//  */
// async function callBBPS({ path, payload, config, lineEndings = 'preserve' }) {
//   const { baseUrl, clientId, encKey, sigKey, sourceId } = config;
//   const url = `${baseUrl}/${sourceId}/${path}`;

//   // Headers + plaintext (possibly normalized)
//   const { headers, body: plaintext } = buildRequest(payload, { lineEndings });

//   // Encrypt + sign
//   const joseEnvelope = await encryptAndSignWithFallback(plaintext, clientId, encKey, sigKey);

//   // POST
//   const resp = await axios.post(url, joseEnvelope, {
//     headers,
//     timeout: 30000,
//     validateStatus: () => true,
//   });

//   // Non-200: try to unwrap JOSE error body if present
 
//   if (resp.status !== 200) {
//     const out = {
//       status: resp.status,
//       error: 'BBPS API call failed',
//       detail: null
//     };

//     if (typeof resp.data === 'object') {
//       out.detail = resp.data;
//     } else if (typeof resp.data === 'string' && resp.data.includes('.')) {
//       try {
//         const decryptedErr = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
//         out.detail = JSON.parse(decryptedErr);
//       } catch (e) {
//         out.detail = { raw: resp.data };
//       }
//     } else {
//       out.detail = { raw: resp.data };
//     }

//     const err = new Error(out.error);
//     // Attach structured response so callers can forward it directly
//     err.response = out;
//     err.status = resp.status;
//     throw err;
//   }


//     if (typeof resp.data === 'object') {
//       out.detail = resp.data;
//       const err = new Error(out.error);
//       err.status = resp.status;
//       err.response = out;
//       throw err;
//     }

//     if (typeof resp.data === 'string' && resp.data.includes('.')) {
//       try {
//         const decryptedErr = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
//         out.detail = JSON.parse(decryptedErr);
//       } catch {
//         out.detail = { raw: resp.data };
//       }
//     } else {
//       out.detail = { raw: resp.data };
//     }

//     const err = new Error(out.error);
//     err.status = resp.status;
//     err.response = out;
//     throw err;
//   }

//   // 200: decrypt + normalize JSON
//   const decrypted = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
//   const finalJson = processResponse(decrypted);
//   return finalJson;
// }

// module.exports = { callBBPS };

const axios = require('axios');
const { buildRequest } = require('./requestUtils');
const { encryptAndSign, verifyAndDecrypt } = require('./symjose');
const { processResponse } = require('./apiresponsemodule');

async function encryptAndSignWithFallback(plaintext, clientId, encKey, sigKey) {
  try {
    return await encryptAndSign(plaintext, clientId, encKey, sigKey);
  } catch (err) {
    if (sigKey && sigKey.length === 64) {
      try {
        const first = sigKey.substring(0, 32);
        return await encryptAndSign(plaintext, clientId, encKey, first);
      } catch (_) {
        const last = sigKey.substring(32, 64);
        return await encryptAndSign(plaintext, clientId, encKey, last);
      }
    }
    throw err;
  }
}

async function callBBPS({ path, payload, config, lineEndings = 'preserve' }) {
  const { baseUrl, clientId, encKey, sigKey, sourceId } = config;
  const url = `${baseUrl}/${sourceId}/${path}`;

  const { headers, body: plaintext } = buildRequest(payload, { lineEndings });
  const joseEnvelope = await encryptAndSignWithFallback(plaintext, clientId, encKey, sigKey);

  const resp = await axios.post(url, joseEnvelope, {
    headers,
    timeout: 30000,
    validateStatus: () => true,
  });

  // 🧠 Error handling
  if (resp.status !== 200) {
    const out = {
      status: resp.status,
      error: 'BBPS API call failed',
      detail: null
    };

    if (typeof resp.data === 'object') {
      out.detail = resp.data;
    } else if (typeof resp.data === 'string' && resp.data.includes('.')) {
      try {
        const decryptedErr = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
        out.detail = JSON.parse(decryptedErr);
      } catch (e) {
        out.detail = { raw: resp.data };
      }
    } else {
      out.detail = { raw: resp.data };
    }

    const err = new Error(out.error);
    err.response = out;
    err.status = resp.status;
    throw err;
  }

  // 🟢 Success: decrypt + process
  const decrypted = await verifyAndDecrypt(resp.data, encKey, null, sigKey, null);
  const finalJson = processResponse(decrypted);
  return finalJson;
}

module.exports = { callBBPS };
