// const { getBillerConfigById } = require('../models/billerConfigModel');
// const { getEnquirePaymentByOrderId } = require('../models/enquirePaymentModel');
// const { getValidationById } = require('../models/validationModel');
// require('dotenv').config();

// async function buildMakePaymentBody(frontendBody) {
//   console.log("🔥 ENTERED buildMakePaymentBody");

//   try {
//     const {
//       billerid,  // <-- ADDED: taken from frontend
//       orderid,
//       validationid,
//       payment_amount,
//       debit_amount,
//       customer,
//       device,
//       authenticators,
//       vpa,
//       cou_conv_fee,
//       bou_conv_fee,
//       selected_bills,
//       billid,
//       pa_ref_no
//     } = frontendBody;

//     // -------------------------------------
//     // 0️⃣ NEW STEP → VALIDATE BILLERID & DETERMINE FLOW
//     // -------------------------------------
//     if (!billerid) {
//       throw new Error("Missing required field: billerid");
//     }

//     // Fetch biller config using billerid from frontend (not validation table!)
//     const billerConfig = await getBillerConfigById(billerid);
//     if (!billerConfig) {
//       throw new Error(`Biller config not found for billerid ${billerid}`);
//     }

//     const onlineValidation = billerConfig.online_validation;
//     console.log("🔎 online_validation flag =", onlineValidation);

//     let flowType = onlineValidation === "Y" ? "instapay" : "adhoc";

//     // If Instapay → validationid is mandatory
//     if (flowType === "instapay") {
//       if (!validationid) {
//         throw new Error("Missing required field: validationid for Instapay biller");
//       }
//     }

//     // If Adhoc → validationid is NOT needed, ignore if present
//     if (flowType === "adhoc") {
//       console.log("🔻 Adhoc flow → Ignoring validationid even if sent");
//       delete frontendBody.validationid;
//     }

//     // -------------------------------------
//     // 1️⃣ Mandatory fields validation
//     // -------------------------------------
//     const requiredKeys = ["orderid", "payment_amount", "debit_amount", "customer", "device", "authenticators"];
//     for (const key of requiredKeys) {
//       if (!frontendBody[key]) throw new Error(`Missing required field: ${key}`);
//     }

//     if (flowType === "instapay") {
//       if (!validationid) throw new Error("Missing required field: validationid");
//     }

//     if (!Array.isArray(authenticators) || authenticators.length === 0) {
//       throw new Error("At least one authenticator is required");
//     }
//     for (const auth of authenticators) {
//       if (!auth.parameter_name || !auth.value) {
//         throw new Error("Authenticator parameter_name and value are required");
//       }
//     }

//     if (!customer.firstname || !customer.mobile) {
//       throw new Error("Customer details incomplete: firstname and mobile required");
//     }

//     if (!device.init_channel) {
//       throw new Error("Device init_channel is required");
//     }

//     if (device.init_channel === "Internet") {
//       if (!device.ip || !device.mac) {
//         throw new Error("Internet device must include ip and mac");
//       }
//     } else if (device.init_channel === "Mobile") {
//       if (!device.imei || !device.os || !device.app) {
//         throw new Error("Mobile device must include imei, os, and app");
//       }
//     }

//     // -------------------------------------
//     // 2️⃣ Fetch order details
//     // -------------------------------------
//     const enquire = await getEnquirePaymentByOrderId(orderid);
//     if (!enquire) throw new Error(`No EnquirePayment found for orderid ${orderid}`);

//     let decodedValidation = {};
//     let customerid = "";
//     let billList = [];
//     let payMultipleBills = "N";

//     // -------------------------------------
//     // 3️⃣ If Instapay → load validation response
//     // -------------------------------------
//     if (flowType === "instapay") {
//       const validationResp = await getValidationById(validationid);
//       if (!validationResp)
//         throw new Error(`No Validation Response found for validationid ${validationid}`);

//       decodedValidation = validationResp.response_json?.decodedData || {};
//       customerid = validationResp.customer_id;
//       billList = decodedValidation.billlist || [];
//       payMultipleBills = decodedValidation.pay_multiple_bills || "N";

//       if (!customerid) throw new Error("Customer ID missing in validation response");
//     }

//     // For adhoc case, take customerid from front-end (same as childline example)
//     if (flowType === "adhoc") {
//       customerid = customer.mobile;
//       payMultipleBills = "N";
//     }

//     const agentid =
//       device.init_channel?.toLowerCase() === 'internet'
//         ? process.env.BBPS_INTERNET_AGENT_ID
//         : process.env.BBPS_MOBILE_AGENT_ID;

//     // -------------------------------------
//     // 4️⃣ Build Payment Account section
//     // -------------------------------------
//     const method = (enquire.payment_method || 'NA').toLowerCase();
//     let payment_account = {};

//     switch (method) {
//       case 'bankaccount':
//         payment_account = {
//           payment_method: "BankAccount",
//           remitter_name: customer.firstname,
//           account_number: "NA"
//         };
//         break;
//       case 'debitcard':
//       case 'creditcard':
//         payment_account = {
//           payment_method: method === 'debitcard' ? "DebitCard" : "CreditCard",
//           remitter_name: customer.firstname,
//           card_start: "NA",
//           card_end: "NA",
//           card_issuer: "NA"
//         };
//         break;
//       case 'upi':
//         if (!vpa) throw new Error("VPA required for UPI payments");
//         payment_account = {
//           payment_method: "UPI",
//           remitter_name: customer.firstname,
//           vpa
//         };
//         break;
//       default:
//         payment_account = {
//           payment_method: "BankAccount",
//           remitter_name: customer.firstname,
//           account_number: "NA",
//           ifsc: "NA"
//         };
//     }

//     // -------------------------------------
//     // 5️⃣ pay_multiple_bills logic (same as before)
//     // -------------------------------------
//     let finalBills = [];
//     let addBreakup = false;
//     let addBillId = false;

//     console.log(`🧾 pay_multiple_bills flag: ${payMultipleBills}`);

//     if (payMultipleBills === "Y") {
//       const hasSelectedBills = Array.isArray(selected_bills) && selected_bills.length > 0;
//       const hasBillId = !!billid;

//       if (!hasSelectedBills && !hasBillId) {
//         throw new Error("For pay_multiple_bills = Y, either billid or selected_bills must be provided.");
//       }

//       if (hasBillId) {
//         addBillId = true;
//         finalBills = [{ billid, amount: payment_amount }];
//       } else if (hasSelectedBills && selected_bills.length === 1) {
//         addBillId = true;
//         finalBills = selected_bills;
//       } else if (hasSelectedBills && selected_bills.length > 1) {
//         addBreakup = true;
//         finalBills = selected_bills;
//       }
//     }
//     else if (payMultipleBills === "M") {
//       if (!billList || billList.length === 0) {
//         throw new Error("No bills found in validation response for pay_multiple_bills = M");
//       }
//       addBreakup = true;
//       finalBills = billList.map(b => ({
//         billid: b.billid,
//         amount: b.net_billamount
//       }));
//     }

//     else if (payMultipleBills === "N") {
//       addBreakup = false;
//       addBillId = false;
//       finalBills = [];
//     }

//     // -------------------------------------
//     // 6️⃣ Final Body
//     // -------------------------------------
//     const payment_body = {
//   customerid,
//   // REMOVED validationid & billerid — added later based on flow
//   source_ref_no: pa_ref_no || orderid,
//   payment_type: flowType,
//   payment_amount,
//   currency: "356",
//   cou_conv_fee: cou_conv_fee || billerConfig.customer_conv_fee || "0.00",
//   bou_conv_fee: bou_conv_fee || "0.00",
//   debit_amount,
//   payment_account,
//   pa_ref_no: pa_ref_no || orderid,
//   customer,
//   metadata: {
//     agent: { agentid },
//     device
//   },
//   risk: [
//     { score_provider: "BD01", score_value: "030", score_type: "TXNRISK" },
//     { score_provider: "BBPS", score_value: "030", score_type: "TXNRISK" }
//   ]
// };

// // -------------------------------------
// // 5A️⃣ Add Flow-Specific Fields
// // -------------------------------------
// console.log("🔍 Flow Type:", flowType);

// // ===== INSTAPAY FLOW =====
// if (flowType === "instapay") {
//   if (!validationid) {
//     throw new Error("Instapay requires a validationid but it is missing");
//   }

//   // Add validationid (MANDATORY)
//   payment_body.validationid = validationid;

//   // Do NOT include billerid or authenticators
//   delete payment_body.billerid;
//   delete payment_body.authenticators;

//   console.log("⚡ Instapay → validationid added, billerid removed.");
// }

// // ===== ADHOC FLOW =====
// if (flowType === "adhoc") {
//   if (!billerid) {
//     throw new Error("Adhoc flow requires billerid but it is missing");
//   }

//   // Add billerid (MANDATORY)
//   payment_body.billerid = billerid;

//   // Add authenticators (MANDATORY)
//   payment_body.authenticators = authenticators;

//   // Do NOT include validationid
//   delete payment_body.validationid;

//   console.log("🟧 Adhoc → billerid + authenticators added, validationid removed.");
// }

//     if (addBillId && finalBills.length > 0) {
//       payment_body.billid = finalBills[0].billid;
//     }

//     if (addBreakup && finalBills.length > 0) {
//       payment_body.payment_amount_breakup = finalBills.map(b => ({
//         billid: b.billid,
//         bill_payment_amount: b.amount
//       }));
//     }

//     console.log(`✅ makePayment body built successfully [Flow: ${flowType}]`);

//     return payment_body;

//   } catch (err) {
//     console.error("❌ Error in buildMakePaymentBody:", err.message);
//     throw err;
//   }
// }

// module.exports = { buildMakePaymentBody };




const { getBillerConfigById } = require('../models/billerConfigModel');
const { getEnquirePaymentByOrderId } = require('../models/enquirePaymentModel');
const { getValidationById } = require('../models/validationModel');
require('dotenv').config();

async function buildMakePaymentBody(frontendBody) {
  console.log("🔥 ENTERED buildMakePaymentBody");

  try {
    const {
      billerid,
      orderid,
      validationid,
      payment_amount,
      debit_amount,
      customer,
      device,
      authenticators,
      vpa,
      cou_conv_fee,
      bou_conv_fee,
      selected_bills,
      billid,
      pa_ref_no
    } = frontendBody;
    
    const requiredKeys = ["orderid", "payment_amount", "debit_amount", "customer", "device", "authenticators"];
    for (const key of requiredKeys) { 
        if (!frontendBody[key]) throw new Error(`Missing required field: ${key}`); 
    }

    // -------------------------------------
    // BASIC VALIDATION
    // -------------------------------------
    if (!orderid) throw new Error("Missing required field: orderid");
    if (!customer || !customer.firstname || !customer.mobile) {
      throw new Error("Customer details incomplete: firstname and mobile required");
    }

    if (!device || !device.init_channel) {
      throw new Error("Device init_channel is required");
    }

    if (device.init_channel === "Internet") {
      if (!device.ip || !device.mac) {
        throw new Error("Internet device must include ip and mac");
      }
    } else if (device.init_channel === "Mobile") {
      if (!device.imei || !device.os || !device.app) {
        throw new Error("Mobile device must include imei, os, and app");
      }
    }

    // -------------------------------------
    // FETCH ENQUIRY RESPONSE
    // -------------------------------------
    const enquire = await getEnquirePaymentByOrderId(orderid);
    if (!enquire) throw new Error(`No EnquirePayment found for orderid ${orderid}`);

    // -------------------------------------
    // GET BILLER CONFIG
    // -------------------------------------
    if (!billerid) {
      throw new Error("billerid is required from frontend for both flows");
    }

    const billerConfig = await getBillerConfigById(billerid);
    if (!billerConfig) throw new Error(`Biller config not found for billerid ${billerid}`);

    const flowType = billerConfig.online_validation === "Y" ? "instapay" : "adhoc";
    console.log("🌀 Flow decided:", flowType);

    let decodedValidation = {};
    let customerid = "";
    let billList = [];
    let payMultipleBills = "N";

    // -------------------------------------
    // INSTAPAY → MUST HAVE VALIDATION
    // -------------------------------------
    if (flowType === "instapay") {
      if (!validationid) {
        throw new Error("Instapay requires validationid, but it is missing");
      }

      const validationResp = await getValidationById(validationid);
      if (!validationResp) throw new Error(`No Validation Response found for validationid ${validationid}`);

      decodedValidation = validationResp.response_json?.decodedData || validationResp.response_json || {};

      customerid = validationResp.customer_id;
      billList = decodedValidation.billlist || [];
      payMultipleBills = decodedValidation.pay_multiple_bills || "N";

      if (!customerid) throw new Error("Customer ID missing in validation response");
    }

    // -------------------------------------
    // ADHOC FLOW
    // -------------------------------------
    if (flowType === "adhoc") {
      customerid = customer.mobile;
      payMultipleBills = "N"; // always single bill
    }

    // -------------------------------------
    // PAYMENT METHOD LOGIC
    // -------------------------------------
    const method = (enquire.payment_method || "NA").toLowerCase();
    let payment_account = {};

    switch (method) {
      case "netbanking":
        payment_account = {
          payment_method: "BankAccount",
          remitter_name: customer.firstname,
          account_number: "NA",
          ifsc: "NA"
        };
        break;

      case "card":
        payment_account = {
          payment_method: method === "card" ? "DebitCard" : "CreditCard",
          remitter_name: customer.firstname,
          card_start: "NA",
          card_end: "NA",
          card_issuer: "NA"
        };
        break;

      case "upi":
        if (!vpa) throw new Error("VPA required for UPI payments");
        payment_account = {
          payment_method: "UPI",
          remitter_name: customer.firstname,
          vpa
        };
        break;

      default:
        payment_account = {
          payment_method: "method",
          remitter_name: customer.firstname,
          account_number: "NA",
          ifsc: "NA"
        };
    }
//   console.log("📌 Validation billList:", billList, "payMultipleBills:", payMultipleBills);
//   console.log("📌 Provided billid from FE:", billid);
 


    // -------------------------------------
    // NEW MULTIPLE BILL LOGIC (UPDATED)
    // -------------------------------------
    let finalBills = [];
    let sendBreakup = false;
    let sendSingleBillId = false;

    const billCount = Array.isArray(billList) ? billList.length : 0;
      if (billCount === 0) {
          if (!billid) {
    throw new Error("Validation returned no billlist → billid is required from frontend");
  }
  sendSingleBillId = true;
  finalBills = [{ billid, amount: payment_amount }];
}

    // If validation returned single bill (or no validation bills for adhoc),
    // allow single-bill flow.
    if (billCount === 1) {
      const resolvedBillId = billid || billList[0].billid;
      if (!resolvedBillId) {
        // should not happen; defensive
        throw new Error("Single bill returned but no billid available from frontend or validation");
      }
      sendSingleBillId = true;
      finalBills = [{ billid: resolvedBillId, amount: payment_amount }];
    }

    // Multiple bills returned from validation → decide per payMultipleBills flag
    if (billCount > 1) {
      if (payMultipleBills === "N") {
        // Only one bill can be paid — FE must provide billid and amount
        if (!billid) {
          throw new Error("pay_multiple_bills = N and validation returned multiple bills → billid is required from frontend");
        }
        // Validate billid exists in validation response
        const matched = billList.find(b => b.billid === billid);
        if (!matched) throw new Error(`Provided billid ${billid} not found in validation response`);
        sendSingleBillId = true;
        finalBills = [{ billid, amount: payment_amount }];
      } else if (payMultipleBills === "M" || payMultipleBills === "Y") {
        // For both M and Y (per your final decision) FE must send selected_bills
        if (!Array.isArray(selected_bills) || selected_bills.length === 0) {
          throw new Error(`pay_multiple_bills = ${payMultipleBills} and validation returned multiple bills → selected_bills (breakup) required from frontend`);
        }
        // Validate each selected bill exists in validation list (best-effort)
        for (const sb of selected_bills) {
          if (!sb.billid || (typeof sb.amount === "undefined" || sb.amount === null)) {
            throw new Error("Each selected_bills entry must include billid and amount");
          }
          const found = billList.find(b => b.billid === sb.billid);
          if (!found) throw new Error(`Selected billid ${sb.billid} not found in validation response`);
        }
        sendBreakup = true;
        finalBills = selected_bills.map(sb => ({ billid: sb.billid, amount: sb.amount }));
      } else {
        throw new Error(`Unknown pay_multiple_bills flag: ${payMultipleBills}`);
      }
    }
    // -------------------------------------
    // BASE PAYMENT BODY
    // -------------------------------------
    const payment_body = {
      customerid,
      source_ref_no: pa_ref_no || orderid,
      payment_type: flowType,
      payment_amount,
      currency: "356",
      cou_conv_fee: cou_conv_fee || billerConfig.customer_conv_fee || "0.00",
      bou_conv_fee: bou_conv_fee || "0.00",
      debit_amount,
      payment_account,
      pa_ref_no: pa_ref_no || orderid,
      customer,
      metadata: {
        agent: {
          agentid:
            device.init_channel?.toLowerCase() === "internet"
              ? process.env.BBPS_INTERNET_AGENT_ID
              : process.env.BBPS_MOBILE_AGENT_ID
        },
        device
      },
      risk: [
        { score_provider: "BD01", score_value: "030", score_type: "TXNRISK" },
        { score_provider: "BBPS", score_value: "030", score_type: "TXNRISK" }
      ]
    };

    // -------------------------------------
    // FLOW SPECIFIC INJECTION
    // -------------------------------------
    if (flowType === "instapay") {
      payment_body.validationid = validationid;
      // instapay should not carry billerid/authenticators at top-level
      delete payment_body.billerid;
      delete payment_body.authenticators;
    }

    if (flowType === "adhoc") {
      payment_body.billerid = billerid;
      payment_body.authenticators = authenticators;
      delete payment_body.validationid;
    }

    // -------------------------------------
    // FINAL: inject either top-level billid (single) OR payment_amount_breakup (multiple)
    // Per your integration: single -> billid, multiple -> payment_amount_breakup
    // -------------------------------------
    if (sendSingleBillId && finalBills.length > 0) {
      // use frontend-provided billid if present; fallback to validation-provided
      payment_body.billid = finalBills[0].billid;
    }

    if (sendBreakup && finalBills.length > 0) {
      payment_body.payment_amount_breakup = finalBills.map(b => ({
        billid: b.billid,
        bill_payment_amount: b.amount
      }));
    }

    console.log(`✅ makePayment body built successfully → Flow: ${flowType}`);
    console.log('Body:', payment_body);
    return payment_body;


  } catch (err) {
    console.error("❌ Error in buildMakePaymentBody:", {
      error: err.message,
      stage: err.stack?.split("\n")[1]?.trim() || "unknown"
    });
    throw err;
  }
}

module.exports = { buildMakePaymentBody };


