// controllers/paymentController.js
const axios       = require('axios');
const crypto      = require('crypto');
const dbConnect   = require('../configs/dbConnection');
const bookTicketModel = require('../model/bookTicketModel');
const smsModel    = require('../../smsapi/model/smsModel');
const { sendConfirmationEmail } = require('../../emailapi/model/mailModel');
const { printticketEmailModel  } = require('../../emailapi/model/printTicketEmailModel');



function getCurrentTimestamp() {
  const pad = n => n.toString().padStart(2, '0');
  const d = new Date();
  const YYYY = d.getFullYear();
  const MM   = pad(d.getMonth() + 1);
  const DD   = pad(d.getDate());
  const hh   = pad(d.getHours());
  const mm   = pad(d.getMinutes());
  const ss   = pad(d.getSeconds());
  return `${YYYY}-${MM}-${DD} ${hh}:${mm}:${ss}`;
}

exports.verifyPayment = async (req, res) => {
  const {
    razorpay_order_id,
    razorpay_payment_id,
    razorpay_signature
  } = req.body;
   console.log("1");
  console.log('rs',razorpay_signature);

  try {
    // 1) Fetch order & blockedTicketId
    const [orderRows] = await dbConnect.query(
      `SELECT 
          ipgid           AS orderId,
          serviceref_id   AS blockedTicketId,
          payeeid,
          tranamount
       FROM onlinepay
       WHERE ipgid = ?
         AND servicetype = 'BusTicket Rpay'
      `,
      [razorpay_order_id]
    );

    if (!orderRows.length) {
      // No booking entry found for this order
      return res.status(404).json({ success: false, message: 'Booking reference not found.' });
    }

    const { orderId, blockedTicketId  , payeeid , tranamount } = orderRows[0];
console.log(orderId, blockedTicketId  , payeeid , tranamount)
 console.log("2");
    const loginUser = payeeid.startsWith('1');

    // 2) Verify Razorpay signature
    const generatedSignature = crypto
      .createHmac('sha256', '0mWsjR5ffOGHE4J2tiRKt1hy')
      .update(`${orderId}|${razorpay_payment_id}`)
      .digest('hex');
      
      console.log('gs' , generatedSignature)
 console.log("3");
    if (generatedSignature !== razorpay_signature) {
      // Signature mismatch -> mark payment failed
      await dbConnect.query(
        'UPDATE onlinepay SET status = ? WHERE ipgid = ?',
        ['failed', orderId]
      );
      //console.log('gs',generatedSignature);
      

      return res.status(400).json({ success: false, message: 'Invalid signature. Payment failed.' });
    } else {
      // 3) Mark payment successful
      await dbConnect.query(
        'UPDATE onlinepay SET status = ? WHERE ipgid = ?',
        ['Transaction Successful', orderId]
      );

      // 4) Book the ticket
      const bookedTicketId = await bookTicketModel.bookTicketRequest(blockedTicketId);
      //const bookedTicketId = "";
       console.log("4");
       console.log("bookedTicketId:", bookedTicketId);

      if (!bookedTicketId) {
         // Booking logic failed -> rollback
         await dbConnect.query(
          'UPDATE onlinepay SET status = ? WHERE ipgid = ?',
          ['booking_failed', orderId]
         );
         if(loginUser){
             console.log(loginUser)
              console.log("5");
             
          // GET DID , UBAL  WHERE UID == PAYEEID
        const [userRows] = await dbConnect.query(
          `SELECT 
              did,
              ubal
           FROM ulogin
           WHERE uid = ?
          `,
          [payeeid]
        );
        if (!userRows.length) {
          console.warn(`No ulogin record found for uid ${payeeid}`);
          return;
        }
        const { did, ubal } = userRows[0];
        
        console.log( did, ubal)
         console.log("6");
        

    
        //GET DBAL WHERE DID== DID 
        if (did) {
          const [dRows] = await dbConnect.query(
            `SELECT 
                dbal
             FROM dlogin
             WHERE did = ?
            `,
            [did]
          );
          if (!dRows) {
            console.warn(`No dlogin record found for did ${did}`);
            return;
          } 
          const dbal = dRows[0].dbal;
         console.log("7");
      }

      //GET ipgbdbal FROM ipgbdmirror

      const [rows] = await dbConnect.query(
        `SELECT *
           FROM ipgbdmirror
          ORDER BY datetime DESC
          LIMIT 1`
      );
       console.log("8");

      if (!rows.length) {
        console.log('No records found in ipgbdmirror.');
        return;
      } 
      const { ipgbdbal } = rows[0];
      console.log('Latest ipgbdbal:', ipgbdbal);
     console.log("9");

      const credit = 0;
      //const newbal = ubal + tranamount + credit ;
      const ipgbdnewbal = parseFloat(ipgbdbal) - parseFloat(tranamount) + parseFloat(credit);

     console.log("10");

      //now insert the new row into ipgbdmirror
      const ts = getCurrentTimestamp();

      await dbConnect.query(
        `INSERT INTO ipgbdmirror 
           (treference, datetime, debit, credit, partyid, ipgbdbal)
         VALUES (?, ?, ?, ?, ?, ?)`,
        [
          orderId,  // your IPG/ORDER ID
          ts,
          tranamount,         // debit
          credit,         // credit
          payeeid,        // partyid (uid)
          ipgbdnewbal     // new ipgbdbal
        ]
      );
     console.log("11");

      //CREDIT OPERARTION -1 (insert t_account) 
      const newbalinterim = parseFloat(ubal) + parseFloat(tranamount);
      await dbConnect.query(
        `INSERT INTO t_account
           (id, treference, bal, tamount_dr, tamount_cr, newbal, datetime)
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          payeeid,         // id (uid)
          orderId,   // treference (ORDERID/IPGID)
          ubal,            // previous balance
          0,               // tamount_dr (debit from user; here zero)
          tranamount,          // tamount_cr (credit to user)
          newbalinterim,    // newbal
          ts
        ]
      );
       console.log("12");

      //  Update ulogin with the new balance
      await dbConnect.query(
        `UPDATE ulogin
            SET ubal = ?
          WHERE uid = ?`,
        [
          newbalinterim,   // new balance
          payeeid          // uid
        ]
      );
       console.log("13");

return res.status(500).json({ 
  success: false, 
  message: `Ticket booking failed. However, your payment has been added to your reward balance. Your current reward balance is ${newbalinterim}.` 
});
                    
         }
         return res.status(500).json({ success: false, message: 'Ticket booking failed.' });
        
      }
       console.log("14");

      // 5) Update uticket entry
      await dbConnect.query(
        'UPDATE uticket SET tin_ticket = ? WHERE blk_ticket = ?',
        [bookedTicketId, blockedTicketId]
      );

      
       console.log("15");

      // 6) Fetch passenger mobile
      const [[{ pmobile, pemail }]] = await dbConnect.query(
        `SELECT pmobile, pemail
           FROM uticket
          WHERE blk_ticket = ?`,
        [blockedTicketId]
      );
  
      if (!pmobile && !pemail) {
        // no contact info—treat as error or just warn
        console.warn(`No contact details found for blk_ticket=${blockedTicketId}`);
      }
       console.log("16");
      
      // 7) Send confirmation email
    let emailResult = null;
    let ptemailResult = null;
    if (pemail) {
      emailResult = await sendConfirmationEmail(pemail, bookedTicketId);
      ptemailResult = await printticketEmailModel(bookedTicketId);
    }
     console.log("17");

      // 6) Send SMS
    let smsResult = null;
    if (pmobile) {
      smsResult = await smsModel.sendSms(pmobile, bookedTicketId ,bookedTicketId, "BobrosMticketv2" , 'MTCKET');
    }

     console.log("18");
//*** new process starts as per NOTES 

      if (loginUser) {

        // GET DID , UBAL  WHERE UID == PAYEEID
        const [userRows] = await dbConnect.query(
          `SELECT 
              did,
              ubal
           FROM ulogin
           WHERE uid = ?
          `,
          [payeeid]
        );
        if (!userRows.length) {
          console.warn(`No ulogin record found for uid ${payeeid}`);
          return;
        }
        const { did, ubal } = userRows[0];
     console.log("19");
    
        //GET DBAL WHERE DID== DID 
        if (did) {
          const [dRows] = await dbConnect.query(
            `SELECT 
                dbal
             FROM dlogin
             WHERE did = ?
            `,
            [did]
          );
          if (!dRows) {
            console.warn(`No dlogin record found for did ${did}`);
            return;
          } 
          const dbal = dRows[0].dbal;

      }
     console.log("20");
      //GET ipgbdbal FROM ipgbdmirror

      const [rows] = await dbConnect.query(
        `SELECT *
           FROM ipgbdmirror
          ORDER BY datetime DESC
          LIMIT 1`
      );

      if (!rows.length) {
        console.log('No records found in ipgbdmirror.');
        return;
      } 
       console.log("21");
      const { ipgbdbal } = rows[0];
      console.log('Latest ipgbdbal:', ipgbdbal);


      const credit = 0;
      //const newbal = ubal + tranamount + credit ;
      const ipgbdnewbal = parseFloat(ipgbdbal) - parseFloat(tranamount) + parseFloat(credit);

     console.log("22");

      //now insert the new row into ipgbdmirror
      const ts = getCurrentTimestamp();

      await dbConnect.query(
        `INSERT INTO ipgbdmirror 
           (treference, datetime, debit, credit, partyid, ipgbdbal)
         VALUES (?, ?, ?, ?, ?, ?)`,
        [
          orderId,  // your IPG/ORDER ID
          ts,
          tranamount,         // debit
          credit,         // credit
          payeeid,        // partyid (uid)
          ipgbdnewbal     // new ipgbdbal
        ]
      );

     console.log("23");
      //CREDIT OPERARTION -1 (insert t_account) 
     newbalinterim = parseFloat(ubal) + parseFloat(tranamount);
      await dbConnect.query(
        `INSERT INTO t_account
           (id, treference, bal, tamount_dr, tamount_cr, newbal, datetime)
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          payeeid,         // id (uid)
          orderId,   // treference (ORDERID/IPGID)
          ubal,            // previous balance
          0,               // tamount_dr (debit from user; here zero)
          tranamount,          // tamount_cr (credit to user)
          newbalinterim,    // newbal
          ts
        ]
      );
     console.log("24");
      //  Update ulogin with the new balance
      await dbConnect.query(
        `UPDATE ulogin
            SET ubal = ?
          WHERE uid = ?`,
        [
          newbalinterim,   // new balance
          payeeid          // uid
        ]
      );
 console.log("25");

      //DEBIT OPERATION -1
      //Insert the debit transaction into t_account
      const newbal1 = 0;
      await dbConnect.query(
        `INSERT INTO t_account
           (id, treference, bal, tamount_dr, tamount_cr, newbal, datetime)
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          payeeid,              // id
          bookedTicketId,   // treference (“FINAL BUS BOOKINGID”)
          newbalinterim,    // bal (the balance before this debit)
          newbalinterim,          // tamount_dr (we’re debiting the full interim balance)
          0,                // tamount_cr (credit is zero for this leg)
          newbal1 ,          // newbal (0)
          ts
        ]
      );
       console.log("26");
      //Update the user’s balance to 0 in ulogin
      await dbConnect.query(
        `UPDATE ulogin
            SET ubal = ?
          WHERE uid = ?`,
        [
          newbal1,  // 0
          payeeid
        ]
      );


 console.log("27");
    //QUERY OFFERUSE FOR A MATCH COUNT blk_ticket if count = 0   (perform CREDIT OPERATION 2 then ) 
    const [[offerUseRow]] = await dbConnect.query(
      `SELECT COUNT(*) AS cnt
         FROM offeruse
        WHERE blk_ticket = ?`,
      [ blockedTicketId ]
    );
     console.log("28");
      console.log("offerUseRow.cnt", offerUseRow.cnt);
      console.log("offerUseRow", offerUseRow);
    if (offerUseRow.cnt === 0) {
      // 2) No prior record found—perform “credit operation‑2” (4% reward)
      const bookingRwd = newbalinterim * 0.04;
      const newBalAfterReward = bookingRwd; // since user balance was zero  
      
      await dbConnect.query(
        `INSERT INTO offeruse
           (uid, umob, umail, offercode, discount, blk_ticket)
         VALUES (?, ?, ?, ?, ?, ?)`,
        [
          payeeid,           // payeeid
          pmobile,          // pmobile
          pemail,         // pemail
          'RewardPoints',     // RewardPoints
          bookingRwd,      // bookingRwd
          blockedTicketId     // blockedTicketId
        ]
      );
     console.log("29");
      await dbConnect.query(
        `INSERT INTO t_account
           (id, treference, bal, tamount_dr, tamount_cr, newbal, datetime)
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          payeeid,               // user id
          orderId,     // original IPG/ORDER ID
          newbal1,                 // balance before reward
          0,                 // tamount_dr
          bookingRwd,        // tamount_cr
          newBalAfterReward , // newbal
          ts
        ]
      );
     console.log("30");
      await dbConnect.query(
        `UPDATE ulogin
            SET ubal = ?
          WHERE uid = ?`,
        [
          newBalAfterReward,
          payeeid
        ]
      );
     console.log("31");
      console.log(`Reward credited: ₹${bookingRwd.toFixed(2)}; new ubal = ₹${newBalAfterReward.toFixed(2)}`);
    }else{
      return res.status(200).json({
        success: true,
        message: 'Payment confirmed, ticket booked.',
        orderId,
        bookedTicketId,
        smsResult,
        emailResult,
        rewardpoints : newBalAfterReward
      });
    }

    console.log("32");
      
    }
    // 8) Respond with success
    return res.status(200).json({
      success: true,
      message: 'Payment confirmed, ticket booked.',
      orderId,
      bookedTicketId,
      smsResult,
      emailResult
    });
     console.log("33");

  }} catch (err) {
    console.error('Payment/booking flow error:', err);
    // Ensure DB reflects booking failure
    if (req.body.razorpay_order_id) {
      await dbConnect.query(
        'UPDATE onlinepay SET status = ? WHERE ipgid = ?',
        ['booking_failed', req.body.razorpay_order_id]
      );
    }
    return res.status(500).json({ success: false, message: err.message });
  }
};
