import _RS from "../../helpers/ResponseHelper";
import Order from "../../models/Order";
import Helper from "../../helpers/Helper";
import OrderStatus from "../../models/OrderStatus";
import Discount from "../../models/Discount";
import moment = require("moment");
import UserSubscription from "../../models/UserSubscription";
import Subscription from "../../models/Subscription";
import Transaction from "../../models/Transaction";
import User from "../../models/User";
import OrderDetail from "../../models/OrderDetail";
import axios from 'axios';
import Payment from "../../models/Payment";
import ProductService from "../../models/ProductService";
import * as mongoose from "mongoose";
import Settings from "../../models/Settings";

export class OrderController {

  /**
  * @api {post} /api/app/customer/order/add Order Add
  * @apiVersion 1.0.0
  * @apiName Order Add
  * @apiHeader {String} Authorization Pass jwt token.
  * @apiGroup Order
  * @apiParam {String} car_id Car Id.
  * @apiParam {Array} service_id Service Id.
  * @apiParam {String} date Date.
  * @apiParam {String} time Time.
  * @apiParam {String} address Address.
  * @apiParam {String} landmark Landmark.
  * @apiParam {String} city City.
  * @apiParam {String} state State.
  * @apiParam {String} country Country.
  * @apiParam {String} latitude Latitude.
  * @apiParam {String} longitude Longitude.
  * @apiParam {String} sub_amount Sub Amount.
  * @apiParam {String} discount_amount Discount Amount.
  * @apiParam {String} discount_code Discount Code.
  * @apiParam {String} discount_id Discount Id.
  * @apiParam {String} subscription_id Subscription Id.
  * @apiParam {String} total Total.
  * @apiParam {String} order_type Order Type ("OnDemand,Subscription").
  * @apiParam {String} payment_id Payment ID.
  * @apiParam {String} payment_status Payment Status ("success,failed,pending").
 */

  static getDatesBetween(startDate, endDate) {
    const dates = [];
    const current = moment(startDate);
    const last = moment(endDate);
    while (current <= last) {
      dates.push(moment(current).format('YYYY-MM-DD'));
      current.add(1, 'days');
    }
    return dates;
  }

  static async add(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const user_id = req.user.id;

      const { car_id, order_type, service_id, house_no, subscription_id, date, time, address, landmark, city, state, country,
        latitude, longitude, sub_total, discount_amount, discount_code, discount_id, total, currency, payment_status, payment_id, payment_method } = req.body;

      const getUserSubscription     =   await UserSubscription.findOne({ subscription_id: subscription_id, user_id: user_id, car_id: car_id });
      const getSetting              =   await Settings.findOne({}).sort({ created_at : -1 });
      const tariffCharge            =   getSetting?.tariff_charge ? Number(getSetting.tariff_charge).toFixed(2) : 0.00;

      if (getUserSubscription) {
        return _RS.api(res, true, req.lang["SubscriptionExists"], {}, startTime);
      }

      const todayDate: any = moment(date).format('YYYY-MM-DD');
      const endDate: any = moment(date).add(30, 'days').format('YYYY-MM-DD');
      const betweenDates = OrderController.getDatesBetween(todayDate, endDate);

      var month = ("0" + (new Date().getMonth() + 1)).slice(-2);
      const unique = new Date().valueOf();
      let genrateCode = await Helper.generatePassword(4, { digits: true, lowercase: false, uppercase: true });
      let randomOrderId = genrateCode + String(unique).substring(10, 12) + month;

      // Add the is_complete key to each object
      const modifiedServiceIdArray = service_id?.map((service) => ({
        ...service,
        is_complete: false,
        complete_on: null,
      }));

      let modifiedSubscriptionObject = {}; // Change to an object

      if (order_type === 'Subscription') { 
        
        try {
          const getSubscription = await Subscription.findById(subscription_id);
      
          if (getSubscription) {
            // Retrieve the ProductService data for all service_ids
            const productServiceDataArray = await Promise.all(getSubscription.services.map(async (service) => {
              const productServiceData = await ProductService.findById(service.service_id);
              if (productServiceData) {
                return productServiceData.toObject();
              } else {
                return null; // Handle the case where ProductService data is not found
              }
            }));

            // Merge the ProductService data into the existing getSubscription object
            for (let i = 0; i < getSubscription.services.length; i++) {
              getSubscription.services[i] = {
                ...getSubscription.services[i].toObject(),
                ...productServiceDataArray[i],
                is_complete: false, // Default value for is_complete
                complete_on: null,  // Default value for complete_on
                total_service: productServiceDataArray[i].no_of_time || 0
              };
            }

            // Add the modified getSubscription to the modifiedSubscriptionObject
            modifiedSubscriptionObject = {
              ...modifiedSubscriptionObject,
              ...getSubscription.toObject(),
            };
          }
        } catch (error) {
          console.error("Error:", error);
        }
      }

      // modifiedSubscriptionObject will now contain the modified subscription data

      const currentDate = new Date();
      const expiredDate = new Date(currentDate.getTime() + 24 * 60 * 60 * 1000); // Add 24 hours (in milliseconds) 

      let order_location = {
        type: "Point",
        coordinates: [parseFloat(longitude),parseFloat(latitude)],
      };

      
      const addOrder      =   await new Order({
        random_order_id   :   randomOrderId,
        user_id           :   user_id,
        car_id            :   car_id,
        service_id        :   service_id ? modifiedServiceIdArray : null,
        subscription_id   :   order_type == 'Subscription' ? subscription_id : null,
        subscription      :   order_type == 'Subscription' ? modifiedSubscriptionObject : null,
        date              :   date,
        time              :   time,
        address           :   address,
        landmark          :   landmark,
        city              :   city,
        state             :   state,
        country           :   country,
        currency          :   currency,
        latitude          :   latitude,
        longitude         :   longitude,
        house_no          :   house_no,
        sub_total         :   sub_total,
        discount_amount   :   discount_amount ? discount_amount : null,
        discount_code     :   discount_code ? discount_code : null,
        discount_id       :   discount_id ? discount_id : null,
        total             :   total,
        tariff_charge     :   tariffCharge,
        current_status    :   'new',
        status            :   'new',
        date_time_stamp   :   date + " " + time,
        order_type        :   order_type,
        payment_status    :   payment_method == 'Online' ? 'pending' : 'Cod',
        payment_method    :   payment_method,
        order_expire_on   :   expiredDate,
        order_location
      }).save();

      await new OrderStatus({ order_id: addOrder._id, mark_by: null, mark_on: new Date(), status: 'new' }).save();

      await new Transaction({
        transaction_id    :   'lcw-' + startTime + month,
        discount_code     :   discount_code ? discount_code : null,
        total             :   total,
        tariff_charge     :   tariffCharge,
        sub_total         :   sub_total,
        order_id          :   addOrder._id,
        subscription_id   :   order_type == 'Subscription' ? modifiedSubscriptionObject : null,
        service_id        :   service_id ? modifiedServiceIdArray : null,
        type              :   order_type == 'Subscription' ? 'Subscription' : 'OnDemand',
        payment_status    :   payment_method == 'Online' ? 'pending' : 'Cod',
        payment_method    :   payment_method,
        order_expire_on   :   expiredDate,
      }).save();

      if (payment_method == 'Cod') {
        const notiTitle = "Your cod order has been placed successfully";
        const notiDesription = "Order ID is " + addOrder.random_order_id + " & placed on " + moment(addOrder.created_at).format('DD-MM-YYYY');
        await Helper.sendNotification(addOrder.user_id, addOrder.user_id, notiTitle, notiDesription);
      }

      // Related to subscription
      if (subscription_id && subscription_id != null && order_type === "Subscription") { // && payment_status === 'success'

        const getSubscription = await Subscription.findById(subscription_id);

        // Loop from today to 30 days (Monthly Data Creation)
        betweenDates.forEach(async element => {
          const orderDetails = {
            order_id: addOrder._id,
            random_order_id: addOrder.random_order_id,
            date: element,
            service_id: service_id,
            subscription_id: order_type == 'Subscription' ? subscription_id : null,
            subscription: order_type == 'Subscription' ? modifiedSubscriptionObject : null,
            time: time,
            user_id: user_id,
            car_id: car_id,
            latitude: latitude,
            longitude: longitude,
            address: address,
            house_no: house_no,
            currency: currency,
            landmark: landmark,
            city: city,
            state: state,
            country: country,
            status: 'new',
            current_status: 'new',
            date_time_stamp: element + " " + time
          }
          await new OrderDetail(orderDetails).save();
        })

        const checkSubscriptionExists = await UserSubscription.findOne({ user_id: user_id, subscription_id: subscription_id, car_id: car_id })

        if (!checkSubscriptionExists) {
          await UserSubscription.create({
            user_id: user_id,
            start_date: todayDate,
            end_date: endDate,
            subscription: order_type == 'Subscription' ? modifiedSubscriptionObject : null,
            car_id: car_id,
            subscription_type: "Month",
            subscription_name: getSubscription?.name,
            subscription_no: "lamsa-" + startTime,
          });

          await User.findById(user_id).updateOne({ $push: { subscription_id: subscription_id } });

        } else {

          const updateSubsciptionData = {
            end_date: checkSubscriptionExists.end_date > moment().format('YYYY-MM-DD') ?
              moment(checkSubscriptionExists.end_date).add(30, 'days').format('YYYY-MM-DD') :
              moment().add(30, 'days').format('YYYY-MM-DD'),
            // subscription_service    :   getSubscription.services,
            // amount                  :   getSubscription.discount,
          }

          const orderDetail = await OrderDetail.findOne({ user_id: user_id, subscription_id: subscription_id, car_id: checkSubscriptionExists.car_id }).sort({ date: -1 });


          const todayDate1: any = orderDetail.date > moment().format('YYYY-MM-DD') ? moment(orderDetail.date).format('YYYY-MM-DD') : moment().format('YYYY-MM-DD');
          const endDate1: any = orderDetail.date > moment().format('YYYY-MM-DD') ? moment(orderDetail.date).add(30, 'days').format('YYYY-MM-DD') : moment().add(30, 'days').format('YYYY-MM-DD');

          const betweenDates1 = OrderController.getDatesBetween(todayDate1, endDate1);

          // Loop from today to 30 days (Monthly Data Creation)
          betweenDates1.forEach(async element => {
            const orderDetails = {
              order_id: addOrder._id,
              random_order_id: addOrder.random_order_id,
              date: element,
              service_id: service_id,
              subscription_id: order_type == 'Subscription' ? subscription_id : null,
              subscription: order_type == 'Subscription' ? modifiedSubscriptionObject : null,
              time: time,
              user_id: user_id,
              car_id: car_id,
              latitude: latitude,
              longitude: longitude,
              address: address,
              house_no: house_no,
              currency: currency,
              landmark: landmark,
              city: city,
              state: state,
              country: country,
              status: 'new',
              current_status: 'new',
              date_time_stamp: element + " " + time
            }
            await new OrderDetail(orderDetails).save();
          })

          const updatedSubscription = await UserSubscription.findOneAndUpdate({ _id: checkSubscriptionExists._id }, updateSubsciptionData, { new: true });
        }
      }

      // // Update Payment Status
      // addOrder.payment_status       =   payment_status;
      // addOrder.payment_received_on  =   payment_status == 'success' ? new Date() : null;
      // addOrder.payment_id           =   payment_id;
      // addOrder.save();

      // await Transaction.findOne({ order_id : addOrder._id }).updateOne({ payment_status  : payment_status })

      // Send Notification Start
      // const notiTitle                 =   "Your order has been placed successfully";
      // const notiDesription            =   "Order ID is " + addOrder.random_order_id + " & placed on " + moment(addOrder.created_at).format('DD-MM-YYYY');
      // Helper.sendNotification(addOrder.user_id, addOrder.user_id, notiTitle, notiDesription); 
      // Send Notification End 


      //Send Request To nearest Washers  

      if (order_type != 'Subscription') {

        const setting = await Settings.findOne({})

        const maxDistance = setting ? (setting.radius * 1000) : 50000;
        const radius = maxDistance / 6371;

        const source_longitude = parseFloat(longitude); //
        const source_latitude = parseFloat(latitude)

        // const geoNearQuery = {
        //   near: {
        //     type: "Point",
        //     coordinates: [source_longitude, source_latitude],
        //   },
        //   distanceField: "Distance",
        //   maxDistance: radius,
        //   query: { type: 'Washer', is_active: true },
        //   spherical: true,
        // };

        // const washers = await User.aggregate([
        //   {
        //     $geoNear: geoNearQuery,
        //   },
        // ]) 

        // let datase = await User.find({
        //   is_active: true,
        //   type: 'Washer',
        //   $and: [
        //     {
        //       user_location: {
        //         $geoWithin: {
        //           $centerSphere: [[source_longitude, source_latitude], radius],
        //         },
        //       },
        //     },
        //   ],
        // }) 

        let datas = await User.find({
          is_active: true,
          type: 'Washer',
          user_location:{ 
            $near :
            {
              $geometry: { type: "Point",  coordinates: [ source_longitude, source_latitude ] },
              $minDistance: 10,
              $maxDistance: setting ? (setting.radius * 1000) :50000
            }
         }
        })

        console.log('washers', JSON.stringify(datas));

        datas.forEach(async (item) => {
          //  Send Request Notification Start
          const notiTitle = "You have a new service Request";
          const notiDesription = "Order ID is " + addOrder.random_order_id + " & placed on " + moment(addOrder.created_at).format('DD-MM-YYYY');
          const data = {
            type: 'SERVICE_REQUEST',
            order_id: addOrder._id + '',
            order_type
          }
          Helper.sendNotification(addOrder.user_id, item._id, notiTitle, notiDesription, data);
        })
      }

      return _RS.api(res, true, req.lang["OrderPlacedSuccess"], addOrder, startTime);

    } catch (err) {
      return next(err);
    }
  }

  /**
   * @api {post} /api/app/customer/order/list Order List
   * @apiVersion 1.0.0
   * @apiName Order List
   * @apiHeader {String} Authorization Pass jwt token.
   * @apiGroup Order
   * @apiParam {String} filter Filter By Status ("new, cancel, complete, in-progress").
   * @apiParam {String} upcoming_wash View All Upcoming Wash (true, false).
  */

  static async list(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const user_id = req.user.id;
      const today = moment().format('YYYY-MM-DD');

      const { filter, upcoming_wash } = req.body;

      let filteredByQuery: any = {};

      if (upcoming_wash == true) {
        filteredByQuery.date = { $gte: today };
      }

      let populateData = [
        {
          path: "user_id",
        },
        {
          path: "washer_id",
        },
        {
          path: "discount_id",
        },
        {
          path: "car_id",
          populate: ([
            {
              path: "make_id",
              select: "name image",
            },
            {
              path: "model_id",
              select: "name",
            },
            {
              path: "color_id",
              select: "color",
            },
            {
              path: "avatar_id",
              select: "image",
            }
          ])
        },
      ];

      // { status : filter ? filter : { $in: ['new','assign','accept','confirm','reach','in-progress','complete','cancel'] } };

      const userId: any = { user_id: user_id };
      const sortBy: any = { created_at: -1 };
      const status: any = { status: filter ? filter : { $in: ['new', 'in-progress', 'complete', 'cancel'] } };

      const onDemandOrder = await Order.find(userId).find(filteredByQuery).find(status).sort(sortBy).populate(populateData);

      return _RS.api(res, true, req.lang["OrderList"], onDemandOrder, startTime);
    } catch (error) {
      next(error);
    }
  }


  /**
  * @api {get} /api/app/customer/order/detail/:id Order Detail
  * @apiVersion 1.0.0
  * @apiName Order Detail
  * @apiHeader {String} Authorization Pass jwt token.
  * @apiGroup Order
  * @apiParam {String} order_id Order ID.
 */

  static async orderDetail(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const user_id = req.user.id;
      const order_id = req.params.id;

      let populateData = [
        {
          path: "washer_id",
        },
        {
          path: "user_id",
        },
        {
          path: "car_id",
          populate: ([
            {
              path: "make_id",
              select: "name image",
            },
            {
              path: "model_id",
              select: "name",
            },
            {
              path: "color_id",
              select: "color",
            },
            {
              path: "avatar_id",
              select: "image",
            }
          ])
        },
      ];

      const orderDetail = await Order.findById(order_id).findOne({ user_id: user_id }).populate(populateData);

      const subscriptionOrder = await OrderDetail.find({ order_id: order_id }).find({ user_id: user_id }).sort({ date: 1 }).populate(populateData);

      const subscriptionOrderDetail = await OrderDetail.findById(order_id).find({ user_id: user_id }).populate(populateData);

      return _RS.api(res, true, req.lang["OrderList"], { orderDetail, subscriptionOrder, subscriptionOrderDetail }, startTime);
    } catch (error) {
      next(error);
    }
  }

  /**
   * @api {post} /api/app/customer/order/rate-review Order Rate And Review
   * @apiVersion 1.0.0
   * @apiName Rate And Review
   * @apiHeader {String} Authorization Pass jwt token.
   * @apiGroup Order
   * @apiParam {String} order_id Order ID.
   * @apiParam {Number} rate Rate.
   * @apiParam {String} review Review.
   * @apiParam {String} order_type Order Type("OnDemand","Subscription").
  */

  static async rateReview(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const { order_id, order_type, rate, review } = req.body;

      let getOrder: any = {};

      if (order_type == 'OnDemand') {
        getOrder = await Order.findOne({ _id: order_id, user_id: req.user.id });
      } else {
        getOrder = await OrderDetail.findOne({ _id: order_id, user_id: req.user.id });
      }

      if (!getOrder) {
        return _RS.api(res, false, req.lang["OrderNotFound"], {}, startTime);
      }

      if (getOrder.status != 'complete') {
        return _RS.api(res, false, req.lang["OrderNotComplete"], {}, startTime);
      }

      if (getOrder.is_rate == true) {
        return _RS.api(res, false, req.lang["AlreadyRated"], {}, startTime);
      }

      getOrder.is_rate = true,
        getOrder.rate = rate,
        getOrder.review = review,
        getOrder.save();

      // Send Notification Start
      const notiTitle = "Rating & review received by customer";
      const notiDesription = "Order ID is " + getOrder.random_order_id;
      Helper.sendNotification(getOrder.user_id, getOrder.washer_id, notiTitle, notiDesription);
      // Send Notification End

      return _RS.api(res, true, req.lang["ReviewSubmitSuccess"], getOrder, startTime);

    } catch (err) {
      next(err);
    }
  }

  /**
   * @api {post} /api/app/customer/order/discount-apply Discount Apply
   * @apiVersion 1.0.0
   * @apiName Discount Apply
   * @apiHeader {String} Authorization Pass jwt token.
   * @apiGroup Order
   * @apiParam {String} discount_code Discount Code.
   * @apiParam {Number} total Total.
  */

  static async discountApply(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const { discount_code, total } = req.body;

      const getCode = await Discount.findOne({ code: discount_code, is_active: true });

      if (!getCode) {
        return _RS.api(res, false, req.lang["DiscountCodeNotFound"], {}, startTime);
      }

      if (getCode.min_amount > total) {
        return _RS.api(res, false, req.lang["DiscountCodeMinAmount"], {}, startTime);
      }

      if ((moment(getCode.from_date).format('YYYY-MM-DD') > moment().format("YYYY-MM-DD"))) {
        return _RS.api(res, false, req.lang["DiscountCodeInvalid"], {}, startTime);
      }

      if ((moment().format("YYYY-MM-DD") >= moment(getCode.to_date).format('YYYY-MM-DD'))) {
        return _RS.api(res, false, req.lang["DiscountCodeExpired"], {}, startTime);
      }

      let calculateDiscount = 0;

      if (getCode.type == 'flat') {
        calculateDiscount = getCode.amount;
      } else {
        calculateDiscount = (getCode.percentage / 100) * total;
      }

      const totalAmount = total - calculateDiscount;

      const response = {
        discount_id     :   getCode._id,
        discount_code   :   getCode.code,
        discount_amount :   calculateDiscount,
        sub_total       :   total,
        total           :   totalAmount
      }

      return _RS.api(res, true, req.lang["DiscountApplySuccess"], response, startTime);

    } catch (err) {
      next(err);
    }
  }

  /**
  * @api {post} /api/app/customer/order/cancel-order
  * @apiVersion 1.0.0
  * @apiName Cancel Order
  * @apiHeader {String} Authorization Pass jwt token.
  * @apiGroup Order
  * @apiParam {String} order_id Order ID.
  * @apiParam {String} order_type Order Type("OnDemand","Subscription").
 */

  static async cancelOrder(req, res, next) {
    try {
      const cancel = 'cancel';
      const startTime = new Date().getTime();
      const { order_id, order_type } = req.body;
      const user_id = req.user.id;

      const getOrder = await Order.findById(order_id);

      if (!getOrder) {
        return _RS.api(res, false, req.lang["OrderNotFound"], {}, startTime);
      }

      getOrder.current_status = cancel
      getOrder.status = cancel
      getOrder.save();

      const getSubOrder = await OrderDetail.find({ order_id: getOrder.order_id });

      if (getSubOrder && getSubOrder.length > 0) {
        await OrderDetail.updateMany({ order_id: getOrder.order_id }, { $set: { current_status: cancel, status: cancel } });
      }

      await new OrderStatus({ order_id: order_id, mark_by: user_id, mark_on: new Date(), status: cancel }).save();

      // Send Notification Start
      const notiTitle = "Order has been cancelled successfully";
      const notiDesription = "Order to your order ID " + getOrder.random_order_id;
      Helper.sendNotification(user_id, user_id, notiTitle, notiDesription);
      // Send Notification End

      return _RS.api(res, true, req.lang["OrderCancelSuccess"], getOrder, startTime);

    } catch (err) {
      next(err);
    }
  }





  /*
  *
  * ===========================================================================================================================================
  * ================================================= Thawani Payment Gateway API =============================================================
  * ===========================================================================================================================================
  * 
  * */


  /**
   * @api {post} /api/app/customer/order/payment Payment Intent
   * @apiVersion 1.0.0
   * @apiName Payment Intent
   * @apiHeader {String} Authorization Pass jwt token.
   * @apiGroup Payment
   * @apiParam {String} order_id Order ID.
  */


  static async paymentIntent(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const { currency, order_id } = req.body;

      if (!order_id) {
        return _RS.api(res, true, "Order id is mandatory", {}, startTime);
      }

      const getOrder = await Order.findById(order_id);
      const user = await User.findById(getOrder.user_id);

      const options = {
        method: 'POST',
        url: process.env.THAWANI_CHECKOUT_PAYMEMNT_URL,
        headers: {
          'Content-Type': 'application/json',
          Accept: 'application/json',
          'thawani-api-key': process.env.THAWANI_SECRET_KEY,
        },

        data: {
          customer_id : user._id,
          client_reference_id: user._id + startTime,
          currency: currency ? currency : 'OMR',
          save_card_on_success: true,
          expire_in_minutes: 30,
          mode: 'payment',
          products: [{ name: 'Order', quantity: 1, unit_amount: getOrder.total * 1000 }],
          success_url: process.env.THAWANI_SUCCESS_PAYMEMT_URL + order_id,
          cancel_url: process.env.THAWANI_CANCEL_PAYMEMT_URL + order_id,
          return_url: process.env.THAWANI_RETURN_PAYMEMT_URL + order_id,
          metadata: {
            email: user.email,
            phone: '+' + user.country_code + user.mobile_number,
            name: user.name,
            orderId: order_id,
          }
        }
      };

      try {
        const { data } = await axios.request(options);

        console.log(data, "Thawani Payment URL");

        if (data.success) {
          const URL = `https://uatcheckout.thawani.om/pay/${data.data.session_id}?key=${process.env.THAWANI_PUBLISH_KEY}`

          getOrder.payment_session_id = data.data.session_id;
          getOrder.order_expire_on = null;
          getOrder.save();

          await new Payment({
            user_id: getOrder.user_id,
            order_id: getOrder._id,
            pay_url: URL,
            total: getOrder.total,
            request: JSON.stringify(options),
            response: JSON.stringify(data)
          }).save();

          return _RS.api(res, true, 'Please wait.. we will redirecting you to payment page', URL, startTime);
        } else {
          return _RS.api(res, false, 'Something went wrong, Please try again later', {}, startTime);
        }

      } catch (error) {
        console.error(error, "error");
        return _RS.api(res, false, error, {}, startTime);
      }

    } catch (err) {
      next(err);
    }
  }

  static async paymentStatusUpdate(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const { order_id } = req.body;
      const getOrder = await Order.findById(order_id);
      const subOrder = await OrderDetail.find({ order_id: order_id });

      if (!order_id) {
        return _RS.api(res, true, 'Something went wrong, Please try again later', {}, startTime);
      }

      const options = {
        method: 'GET',
        url: process.env.THAWANI_RETRIEVE_PAYMEMNT_URL + getOrder.payment_session_id,
        headers: {
          Accept: 'application/json',
          'thawani-api-key': process.env.THAWANI_SECRET_KEY,
        }
      };

      try {

        const { data } = await axios.request(options);

        // Update Payment Status
        getOrder.payment_status = data.data.payment_status;
        getOrder.payment_received_on = data.data.payment_status == 'paid' ? new Date() : null;
        getOrder.save();

        if (subOrder && subOrder.length > 0) {
          await OrderDetail.find({ order_id: order_id }).updateMany({ payment_session_id: data.data.session_id, payment_status: data.data.payment_status });
        }

        await Transaction.findOne({ order_id: getOrder._id }).updateOne({ payment_status: data.data.payment_status })

        // Send Notification Start
        const notiTitle = "Your payment has been received successfully";
        const notiDesription = "Order ID is " + getOrder.random_order_id + " & placed on " + moment(getOrder.created_at).format('DD-MM-YYYY');
        await Helper.sendNotification(getOrder.user_id, getOrder.user_id, notiTitle, notiDesription);

        return _RS.api(res, true, 'Your payment has been received successfully', data, startTime);

      } catch (error) {

        console.error(error, "error");
        return _RS.api(res, false, error, {}, startTime);
      }

    } catch (err) {
      next(err);
    }
  }

  static async paymentView(req, res, next) {
    try {
      const startTime = new Date().getTime();
      const getOrder = await Order.findOne({ _id: req.params.id });
      return _RS.ok(res, "SUCCESS", "Payment order data get successfully", getOrder, startTime);
    } catch (err) {
      next(err);
    }
  }

  static async paymentWebHookGet(req, res, next) {
    try {
      const startTime = new Date().getTime();
      console.log("paymentWebHookGet");
      return _RS.ok(res, "SUCCESS", "Payment web hook get successfully", {}, startTime);

    } catch (err) {
      next(err);
    }
  }

  static async paymentWebHookPost(req, res, next) {
    try {
      const startTime = new Date().getTime();
      console.log("paymentWebHookPost");
      return _RS.ok(res, "SUCCESS", "Payment web hook post successfully", {}, startTime);

    } catch (err) {
      next(err);
    }
  }

}
