const moment = require('moment')
const uniqid = require('uniqid');
//packages
const Request = require('../models/request')
const Product = require('../models/product')
const Project = require('../models/Projects')
const ProjectTask = require('../models/projectTask')
const CustomerOrder = require('../models/customerOrder')
const CustomerOrderProduct = require('../models/customerOrderProduct')
const RequestPartner = require('../models/requestPartners')
const RequestUpdates = require('../models/requestUpdates')
const Admin = require('../models/admin')
const RequestActivity = require('../models/RequestActivity')
const Community = require('../models/community')
const { empty } = require('../Helpers/Common')
const Client = require("../models/client")
const OnboardWorkFlowFields = require("../models/onboardWorkflowFields")
const OnboardWorkFlowStages = require("../models/onboardWorkFlowStages")
const OnboardWorkFlowQuestionnaires = require("../models/onboardWorkflowQuestionnaires")
const sgMail = require('@sendgrid/mail')
const { SENDGRID_API_KEY, BASE_URL, portalName, SEND_EMAIL } = require("../constants/constant")
const { rfqEmail } = require('../constants/emailTemplates');
const RequestProposals = require('../models/requestProposals')
const Proposals = require('../models/proposal')
let currentDate = moment().unix()
const axios = require('axios')
const {
    clientId,
    clientSecret,
    redirectUri,
    authCode,
    companyId,
    accessToken,
    refreshToken,
    getNewAccessToken,
    realmId,
    PRODUCTION,
    rfpAssetAccId,
    rfpExpAccId,
    rfpIncAccId
  } = require('../quickbook/quickbook.js');
  const nodemailer = require('nodemailer');


  const transporter = nodemailer.createTransport({
    host: 'mail.signwisesolutions.com', 
    port: 465, 
    secure: true, 
    auth: {
      user: 'noreply@signwisesolutions.com', 
      pass: 'signwise@2024', 
    },
  });



const getAllProposals = async (req, res) => {
    try {
        let userId = req.body.userId
        let userType = req.body.userType
        let page = req.body.page
        let search = req.body.search
        let rowPerpage = req.body.rowsPerPage
        let where = req.body.where
        let sort = req.body.sort
        let fromDate = req.body.from
        let toDate = req.body.to
        let data = await Proposals.getAllProposals(null, userId, userType, page, rowPerpage, search, where,sort,fromDate,toDate)

        let requestTeam = await Request.getAllTeamBatch()
        let services = await Request.getServices(null)
        let products = await Product.getAllProducts(false);
        products = products.filter(row => row.inhouse === 0)
        let labourCostServices = await Product.getAllLabourCostServices();
        labourCostServices = labourCostServices.filter(row => row.inhouse === 0)
        let community = await Community.getAllCommunities();
        let workflows = await Client.getAllWorkflows();
        let materials = await Product.getAllInhouseAndClientOwnedMaterials(true);
        for (const data of products) {
            let result = await Product.getServiceByProduct(data.id);

            data.services = result
        }
        res.send({
            status: 1,
            data: data,
            requestTeam: requestTeam,
            services: services,
            products: products,
            community: community,
            labourCostServices,
            workflows,
            materials,
            message: 'Request fetched successful'
        })
    } catch (error) {
        console.log(error)
        res.send({ status: 0, message: 'Request fetched failed' });
    }
}

//////////////////////////////////////////////////////////quickbook
let uniqueRFQid=null
const addRpfToQuickBooks = async (productData) => {
    try {
      console.log('Refreshing access token...');
      const token = await getNewAccessToken();
  
      const currentDate = moment().toISOString();
      const asOfDate = moment().format('YYYY-MM-DD');
  
      // QuickBooks product data structure
      const quickBooksProductData = {
        Name: productData.name,
        Description: productData.description,
        UnitPrice: productData.price,
        Type: "Inventory",
        IncomeAccountRef: {
           value: rfpIncAccId
        },
        AssetAccountRef: {
            value: rfpAssetAccId
        },
        ExpenseAccountRef: {
         value: rfpExpAccId
        },
        TrackQtyOnHand: true,
        QtyOnHand: productData.unit_qty,
        InvStartDate: asOfDate,
      };
  
      console.log("QuickBooks Product Data:", JSON.stringify(quickBooksProductData, null, 2));

      const apiUrl = PRODUCTION
      ? `https://quickbooks.api.intuit.com/v3/company/${realmId}/item`  // Production URL
      : `https://sandbox-quickbooks.api.intuit.com/v3/company/${realmId}/item`; // Sandbox URL

  
      const response = await axios.post(
        apiUrl,
        quickBooksProductData,
        {
          headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
            Accept: 'application/json'
          }
        }
      );
  
      if (response.status === 200) {
        console.log("Product has been successfully added to QuickBooks:", response.data);
        console.log("Unique ID of the added product:", response.data.Item.Id);
        uniqueRFQid = Number(response.data.Item.Id)
      } else {
        console.error("Failed to add the product to QuickBooks:", response.data);
      }
    } catch (error) {
      console.error("Error adding product to QuickBooks:", error.response ? error.response.data : error.message);
      const faultType = error.response?.data?.Fault?.type;
      if (faultType === 'AUTHENTICATION') {
        console.error('Authentication error:', JSON.stringify(error.response?.data, null, 2));
        if (error.response?.data?.Fault?.Error?.[0]?.Detail === 'invalid_grant') {
          console.error('Refresh token is invalid or expired. Please reauthorize your application.');
          // You can add logic here to notify the user/admin or handle reauthorization
        }
      } else if (faultType === 'ValidationFault') {
        console.error("Validation error adding product to QuickBooks:", JSON.stringify(error.response?.data, null, 2));
      } else {
        console.error("Other error adding product to QuickBooks:", error.response?.data || error.message);
      }
    }
  };



//////////////////////////////////////////////////////////////

const addRfp = async (req, res) => {
    try {
        const { userId, userType, values, taxCategory, userName, address, allLocationSame, quotation
        } = req.body
        console.log('req.bodyyyyyyyyyyyyyyyyy', req.body)
        console.log('req.bodyyyyyyyyyyyyyyyyy values', values)

        let currentDate = moment().unix()
        let currentTime = moment().unix()
        let submission_deadline = values.start // moment(values.start).unix()
        let participation_ends = values.end
        let uploaded = values.avatarUrl;
        let uploadedfile = values.files_upload;
        console.log('bshdfbgisdbgisfigb',uploadedfile)
        let requestdata = {}
        requestdata['name'] = values.name,
            requestdata['description'] = values.description,
            requestdata['markup_type'] = values.markup_type?.id || 1,

            requestdata['notes'] = values.notes || "",
            requestdata['labour_cost_services'] = values.serviceData,
            requestdata['labour_cost'] = values.labour_cost

        if (values.end !== (undefined || null)) {
            requestdata['participation_ends'] = participation_ends
        } else {
            requestdata['participation_ends'] = 0
        }
        requestdata['start_date'] = null
        requestdata['submission_deadline'] = submission_deadline
        if (values.welcome_message == true) {
            requestdata['welcome_message'] = values.welcome_message
            requestdata['subject'] = values.subject,
                requestdata['email_content'] = values.email_content
        } else {
            requestdata['welcome_message'] = false
            requestdata['subject'] = null,
                requestdata['email_content'] = null
        }
        requestdata['type'] = 2
        if (values.draft == true) {
            requestdata['status'] = values.draft
        } else {
            requestdata['status'] = 2
        }
        if (!empty(quotation) && quotation === 1) {
            requestdata['status'] = 8
        }
        requestdata['added_by'] = userId,
            requestdata['timestamp'] = currentTime
        requestdata['thumbnail'] = values.avatarUrl[0]
        requestdata['is_location'] = allLocationSame
        console.log("C", requestdata);

         // ////////////////////////////QB
    // uniqueRFQid=null

    // const productData = {
    //     name: values.name,
    //     description: values.description,
    //     price: values.labour_cost,
    //     unit_qty: values.unit_qty || 1 
    //   };
  
    //  try {
    //      await addRpfToQuickBooks(productData);
    //  } catch (error) {
    //     console.log("error",error)
    //  }
      
    //   if(uniqueRFQid){
    //     requestdata['syncWithQuickbooks'] = 1
    //     requestdata['rfpQbId'] = uniqueRFQid
    //   }
     
////////////////////////////////////Qb

        let result = await Proposals.addProposal(requestdata)

        if(result){
            if (!empty(uploadedfile)) {
                console.log('bshdfbgisdbgisfigb1')
                for (const row of uploadedfile) {
                    let approvedImage = {}
                    approvedImage.name = row.url;
                    approvedImage.extension = row.type;
                    approvedImage.proposal_id = result;
                    approvedImage.added_by = userId
                    approvedImage.timestamp = moment().unix()
                    let upload = await Proposals.addRequestProposaAttachments(approvedImage)
                    console.log('bshdfbgisdbgisfigb1',upload)
                }


            }
        }

        const orderData = {}
        if (result) {
            if (!empty(uploaded)) {
                for (const row of uploaded) {
                    let approvedImage = {}
                    approvedImage.name = row;
                    approvedImage.request_id = result;
                    approvedImage.added_by = userId
                    approvedImage.timestamp = moment().unix()
                    let upload = await Request.addRequestAttachments(approvedImage)
                }

                
            }
            
            console.log("Request*******************", result);
            // orderData['total'] = values.total + (values.taxAmount || 0),
            orderData['total'] = (values.total && values.total > 0) ? values.total + (values.taxAmount || 0) : 0,
            orderData['tax_category'] = taxCategory || null
            orderData['tax_amount'] = values.taxAmount || 0
                // orderData['budget'] = values.budget,
                orderData['budget'] = (values.budget && values.budget > 0) ? values.budget + (values.taxAmount || 0) : 0,
                orderData['extra_discount'] = values.invoice_discount || 0,
                orderData['request_id'] = result,
                orderData['timestamp'] = currentTime,
                orderData["sub_total"] = values.sub_total || 0;
            orderData["tax"] = 0;
            orderData['status'] = 1
            console.log("orderData*******************", orderData);
            let resultData = await Proposals.createCustomerOrder(orderData)

            let requestProduct = {}
            if (resultData) {

                for (const row of values.products) {
                    console.log('row-dsfdfd-------', row);
                    let rowQuantity = row.quantity ? row.quantity : 1;
                    let rowDiscount = row.discount ? row.discount : 0
                    let subTotal = row.retail_price||0 * rowQuantity * row.locationQuantity;
                    let productTotal = (row.retail_price||0 * rowQuantity * row.locationQuantity) - rowDiscount;
                    requestProduct['order_id'] = resultData
                    requestProduct['product_id'] = row.id,
                        requestProduct['product_name'] = row.name,
                        requestProduct['product_price'] = row.price||0,
                        requestProduct['product_retail_price'] = row.markup_type == 1 ? row.price||0 : row.retail_price||0,
                        requestProduct['product_markup'] = row.markup,
                        requestProduct['product_qty'] = rowQuantity,
                        requestProduct['location_quantity'] = row.locationQuantity || 1,
                        requestProduct['product_sub_total'] = row.product_sub_total,
                        requestProduct['product_tax'] = 0,
                        requestProduct['product_total'] = row.product_sub_total||0,
                        requestProduct['workflow'] = row.workflow,
                        requestProduct['discount'] = rowDiscount,
                        requestProduct['timestamp'] = currentTime,
                        requestProduct['status'] = row.status

                    let response = await Proposals.createCustomerOrderProduct(requestProduct)
                    console.log('responseeeeeeeeeeeeeeeeeeeee product', response)
                    
                    if (response) {

                        let result = address.filter(raw => raw.productId === row.id);
                        let data = {}
                        if (result) {
                            for (let i = 0; i < result.length; i++) {
                                data.order_id = response
                                data.product_id = result[i].productId
                                data.address = result[i].address
                                data.city = result[i].city
                                data.state = result[i].state
                                data.zip = result[i].zip.trim()
                                data.timestamp = moment().unix()
                                data.added_by = userId
                                let addLocation = await Request.addLocation(data)
                                console.log("#############", addLocation);
                            }

                        }

                    }
                }
                console.log("selected services", values.selectedServices);
                for (const row of values.selectedServices) {
                    let rowQuantity = row.quantity ? row.quantity : 1;
                    requestProduct['request_id'] = result
                    requestProduct['labour_cost_service_id'] = row.id;
                        requestProduct['recipe_id'] = row.recipe_id || null;
                        requestProduct['product_id'] = row.product_id || null;
                        requestProduct['qty'] = rowQuantity;
                        requestProduct['unit_cost'] = row.unit_cost || row.total_cost;
                        requestProduct['markup'] = !empty(Number(row.markup)) ? row.markup : 0;
                        requestProduct['total_cost'] = !empty(Number(row.total)) ? Number(row.total) : (requestProduct['unit_cost'] * requestProduct['qty']);
                        requestProduct['jobcost_unit_cost'] = row.unit_cost || row.total_cost || 0;
                        requestProduct['jobcost_quantity'] = rowQuantity || 0;
                        requestProduct['jobcost_total_cost'] = requestProduct['jobcost_unit_cost'] * requestProduct['jobcost_quantity'];

                    let response = await Proposals.addRequestServices(requestProduct)
                }

                for (const row of values.materials) {
                    console.log('responseeeeeeeeeeeeeeeeeeeee product 1')
                    console.log('row-dsfdfd-------', row);
                    let rowQuantity = row.quantity ? row.quantity : 1;
                    let rowDiscount = row.discount ? row.discount : 0
                    let subTotal = row.retail_price||0 * rowQuantity * row.locationQuantity;
                    let productTotal = (row.retail_price||0 * rowQuantity * row.locationQuantity) - rowDiscount;
                    requestProduct['order_id'] = resultData
                    requestProduct['product_id'] = row?.id,
                        requestProduct['product_name'] = row?.name,
                        // requestProduct['product_price'] = row.price||0,
                        // requestProduct['product_retail_price'] = row.markup_type == 1 ? row.price||0 : row.retail_price||0,
                        // requestProduct['product_markup'] = row.markup,
                        requestProduct['product_price'] = 0,
                        requestProduct['product_retail_price'] = 0,
                        requestProduct['product_markup'] = 0,
                        requestProduct['product_qty'] = rowQuantity,
                        requestProduct['location_quantity'] = row?.locationQuantity || 1,
                        requestProduct['product_sub_total'] = row?.product_sub_total || 0,
                        requestProduct['product_tax'] = 0,
                        requestProduct['product_total'] = row?.product_sub_total||0,
                        requestProduct['workflow'] = row.workflow,
                        requestProduct['discount'] = rowDiscount,
                        requestProduct['timestamp'] = currentTime,
                        requestProduct['status'] = row.status
                        requestProduct['material'] = 1

                    let response = await Proposals.createCustomerOrderProduct(requestProduct)
                    if (response) {

                        let result = address.filter(raw => raw.productId === row.id);
                        let data = {}
                        if (result) {
                            for (let i = 0; i < result.length; i++) {
                                data.order_id = response
                                data.product_id = result[i].productId
                                data.address = result[i].address
                                data.city = result[i].city
                                data.state = result[i].state
                                data.zip = result[i].zip.trim()
                                data.timestamp = moment().unix()
                                data.added_by = userId
                                let addLocation = await Request.addLocation(data)
                                console.log("#############", addLocation);
                            }

                        }

                    }
                }

                if (userType != 3) {
                    let partnerData = values.clientsData[0]
                    let subject = empty(quotation) ? 'A new request awaiting your acceptance' : 'A new estimate awaiting your acceptance';
                    let email_content = empty(quotation) ? `You are invited to join New request by ` + userName : `You are invited to join New estimate by ` + userName;
                    if (req.body.values.isCustomMessage) {
                        subject = req.body.values.subject
                        email_content = req.body.values.emailcontent
                    }
                    console.log("############Hifiiiiiiiiii", partnerData);
                    if (partnerData && partnerData.length > 0) {

                        let client = {}
                        let insertedstatus = null
                        let i = 0
                        for (let eachPartner of partnerData) {

                            client['request_id'] = result,
                                client['last_seen'] = currentDate,
                                client['timestamp'] = currentDate,
                                client['added_by'] = userId,
                                client['partner_id'] = eachPartner.id
                            client['accept_status'] = 1;
                            client['status'] = 1
                            insertedstatus = await Proposals.addRequestPartners(client)
                            i++
                        }

                        if (insertedstatus) {

                            let partnerIds = partnerData.map(eachClient => eachClient.id);
                            let tempRequestPartnerArr = partnerData.map(eachClient => eachClient.id + ',' + eachClient.name);


                            let requestdata = {}
                            requestdata['customer_id'] = partnerData[0]['id'];
                            requestdata['customer_name'] = partnerData[0]['name'];
                            requestdata['customer_phone'] = partnerData[0]['phone'];
                            requestdata['customer_address'] = partnerData[0]['address'];
                            requestdata['timestamp'] = currentDate;
                            // let orderId = await Proposals.getCustomerOrderRequestId(result);
                            // if (empty(orderId.customer_name)) {
                            //     await Proposals.updateCustomerOrder(orderId.id, requestdata);
                            // }


                            for (let eachPartner of partnerData) {

                                let welcome = "Hello " + eachPartner['company_name'] + ","

                                sgMail.setApiKey(SENDGRID_API_KEY)
                                let message = rfqEmail()
                                message = message.replace('[emailContent]', email_content)
                                message = message.replace('[CONTENT]', welcome)

                                message = message.replace('[LOGIN_URL]', `${BASE_URL}`)
                                // const msg = {
                                //     to: eachPartner.email, // Change to your recipient
                                //     from: 'nushara@skyniche.com', // Change to your verified sender
                                //     subject: subject,
                                //     text: subject,
                                //     html: message,
                                // }
                                // sgMail
                                //     .send(msg)
                                //     .then(() => {
                                //         console.log('Email sent')
                                //     })
                                //     .catch((error) => {
                                //         console.error(error)
                                //     })

                                const mailOptions = {
                                    to:  eachPartner.email , 
                                    from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
                                    subject: subject,
                                    text: subject,
                                    html: message,
                                  }
                                  try {
                                    if(SEND_EMAIL){
                                    await transporter.sendMail(mailOptions);
                                    console.log('Email sent');
                                    }
                                  } catch (error) {
                                    console.error('##########Err', error);
                                   
                                  }
                            }
                        }
                    }
                    let notification_msg = empty(quotation)
                        ? `🔔 New RFP <strong>${requestdata['name']}</strong> has been added.`
                        : `📄 New Estimate <strong>${requestdata['name']}</strong> has been added.`
                    let notification_url = `official-request/view/${result}`
                    const incrementResult_User = await Admin.incrementField(
                        userId,
                        "noti_count",
                        1
                    );

                    let notificationData_user = {
                        user_id: userId,
                        url: notification_url,
                        timestamp: currentDate,
                        message: notification_msg,
                        status: 1,
                        from_id: userId,
                    };

                    const addNotificationResult_user = await Admin.addNotification(
                        notificationData_user
                    );
                    let adminIds = await Admin.getAllAdminIds();
                    for (let eachadminIds of adminIds) {
                        if (eachadminIds != userId) {
                            let incrementResult = await Admin.incrementField(eachadminIds, 'noti_count', 1)
                            let addNotification = {
                                user_id: eachadminIds,
                                url: notification_url,
                                timestamp: moment().unix(),
                                message: notification_msg,
                                status: 1,
                                from_id: userId,
                            }
                            const addNotificationResult = await Admin.addNotification(addNotification);
                        }
                    }
                    let requestActivity = {}
                    requestActivity['request_id'] = result;
                    requestActivity['activity'] = notification_msg;
                    requestActivity['added_by'] = userId
                    requestActivity['timestamp'] = currentTime
                    // let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
                }
                else {

                    let clientDetails = await Client.getClientByUserId(userId);
                    let subject = 'A new request initiated by client';
                    let email_content = `A new request initiated by client` + userName;
                    let client = {}
                    let insertedstatus = null
                    client['request_id'] = result,
                        client['last_seen'] = currentTime,
                        client['timestamp'] = currentTime,
                        client['added_by'] = userId,
                        client['partner_id'] = clientDetails.id
                    client['accept_status'] = 1;
                    client['status'] = 1
                    insertedstatus = await Proposals.addRequestPartners(client)
                    console.log("###### Client added", insertedstatus);
                    if (insertedstatus) {

                        let requestActivity = {}

                        requestActivity['request_id'] = result,
                            requestActivity['partner_id'] = clientDetails.id,
                            requestActivity['partner_name'] = clientDetails.name,
                            requestActivity['activity'] = `Client,${clientDetails.name} has initiated the Request`,
                            requestActivity['added_by'] = userId,
                            requestActivity['timestamp'] = currentTime,
                            requestActivity['addestatusd_by'] = 1
                        //   let activityResult = await RequestUpdates.addRequestUpdates(requestActivity)
                        let requestdata = {}
                        requestdata['customer_id'] = clientDetails['id'];
                        requestdata['customer_name'] = clientDetails['name'];
                        requestdata['customer_phone'] = clientDetails['phone'];
                        requestdata['customer_address'] = clientDetails['address'];
                        requestdata['timestamp'] = currentDate;
                        let orderId = await Proposals.getCustomerOrderRequestId(result);
                        await Proposals.updateCustomerOrder(orderId.id, requestdata);
                        const request = await Proposals.getRequestById(result)
                        const requestTeams = await Request.getRequestPartnersByIds([clientDetails.id])
                        const requestTeamUserIds = await Request.getRequestTeamUserIds(result)
                        const adminIds = await Admin.getAllAdminIds()



                        // Notification 
                        let notification_msg = !empty(quotation) ?
                            `${clientDetails.name}"</strong> has been initiated new  Estimate  <strong>"${request[0].name}"</strong>."` : `${clientDetails.name}"</strong> has been initiated new  request <strong>"${request[0].name}"</strong>."`
                        let notification_url = `official-request/view/${result}`

                        // Alert assigned user of updation
                        let incrementResult = await Admin.incrementField(userId, "noti_count", 1);
                        let notificationUser = {
                            user_id: userId,
                            url: notification_url,
                            timestamp: currentTime,
                            message: notification_msg,
                            status: 1,
                            from_id: userId,
                        }
                        const addNotificationResult = await Admin.addNotification(notificationUser);
                        for (let request_team_us_id of requestTeamUserIds) {
                            // Alert assigned user of updation
                            let incrementResult = await Admin.incrementField(request_team_us_id, 'noti_count', 1)
                            let addNotification = {
                                user_id: request_team_us_id,
                                url: notification_url,
                                timestamp: currentTime,
                                message: notification_msg,
                                status: 1,
                                from_id: userId,
                            }
                            const addNotificationResult = await Admin.addNotification(addNotification);
                        }
                        for (let adminids of adminIds) {
                            let incrementResult = await Admin.incrementField(adminids, 'noti_count', 1)
                            let addNotification = {
                                user_id: adminids,
                                url: notification_url,
                                timestamp: currentTime,
                                message: notification_msg,
                                status: 1,
                                from_id: userId,
                            }
                            const addNotificationResult = await Admin.addNotification(addNotification);
                        }

                        let welcome = "Hello Admin,"
                        let email_content = empty(quotation) ? `${clientDetails.name}"</strong> has been initiated new  request <strong>"${request[0].name}"</strong>."` :
                            `${clientDetails.name}"</strong> has been initiated new  Estimate <strong>"${request[0].name}"</strong>."`
                        let subject = empty(quotation) ? " New Request from Client" : " New Estimate from Client"
                        let message = rfqEmail()
                        message = message.replace('[emailContent]', email_content)
                        message = message.replace('[CONTENT]', welcome)

                        message = message.replace('[LOGIN_URL]', `${BASE_URL}`)
                        let adminEmails = await Admin.getAllAdminEmails();
                        for (const row of adminEmails) {
                            console.log("$$$$$$$$$$$$$$$nush", row);
                            // const msg = {
                            //     to: row, // Change to your recipient
                            //     from: 'nushara@skyniche.com', // Change to your verified sender
                            //     subject: subject,
                            //     text: subject,
                            //     html: message,
                            // }
                            // sgMail
                            //     .send(msg)
                            //     .then(() => {
                            //         console.log('Email sent')
                            //     })
                            //     .catch((error) => {
                            //         console.error(error)
                            //     })

                            const mailOptions = {
                                to:  row , 
                                from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
                                subject: subject,
                                text: subject,
                                html: message,
                              }
                              try {
                                if(SEND_EMAIL){
                                await transporter.sendMail(mailOptions);
                                console.log('Email sent');
                                }
                              } catch (error) {
                                console.error('##########Err', error);
                               
                              }
                        }
                    }
                }
                res.send({ status: 1, message: empty(quotation) ? "Request has been successfully added!." : "Estimate has been successfully added!." })
            }

            else {
                res.send({ status: 0, message: "Failed to add the request" });
            }
        }

    } catch (error) {
        console.log(error, 'Error in adding request')
        res.send({ message: "Error in adding request" });
    }
}

const getProposalById = async (req, res) => {
    try {
        const { request_id } = req.body;
        let userId = req.body.userId
        let userType = req.body.userType
        // let result = await Request.getRequestById(request_id) 
        let result = await Proposals.getAllProposals(request_id, userId, userType)
        console.log("######Result",result);
        result = result?.data?.map(item => ({
            ...item,
            welcome_message: item.welcome_message === 1 ? true : false
        }));
        let customerData = await Proposals.getCustomerOrderRequestId(request_id,userId)
        let serviceSkill = await Request.getServices(null)
        let products = await Product.getAllProducts(false);

        products = products.filter(row => row.inhouse === 0)
        let projectExisting = false
        let team = []
        if (projectExisting) {
            team = await Project.getAllProjectMembers(projectExisting.id)
        }
        for (const data of products) {
            let result = await Product.getServiceByProduct(data.id);
            data.services = result
        }
        // let requestAwaitingPartners=await RequestPartner.requestAwaitingPartners(request_id,0)
        // let requestRejectedPartners=await RequestPartner.requestAwaitingPartners(request_id,2)
        let requestAcceptedPartners = await Proposals.requestAwaitingPartners(request_id, 1)
        let partner = await Client.getPartnerByUserId(userId);
        let updates = []
        let attachments = []
        let payments = []
        let workflows = await Client.getAllWorkflows();
        let customFieldTemplateId = await Client.getAllFieldTemplatesRfq(request_id)
        let labourCostServices = await Product.getAllLabourCostServices();
        let materials = await Product.getAllInhouseAndClientOwnedMaterials(true);
        labourCostServices = labourCostServices.filter(row => row.inhouse === 0)
        console.log("$############SERrg435646",result);
        let requestServices
        if(result[0]?.proposalId){
            console.log("$############SERrg435646",result[0]?.proposalId);
            requestServices = await Proposals.getVendorServices(result[0]?.proposalId)
        }
        else{
            requestServices = await Proposals.getRequestServices(request_id)
        }
        
        // console.log("$$$$$$$$$$$$",customFieldTemplateId);
        let fieldTemplates = [];
        let i = 0;
        for (const row of customFieldTemplateId) {
            let field_template_ids = await OnboardWorkFlowFields.getfieldTemplatesbyStageId(row.stage_id);
            //  console.log("HIFI", field_template_ids);

            if (!empty(field_template_ids)) {
                let templateData = await OnboardWorkFlowStages.getTemplateFormDataById(field_template_ids, 0, 0, 1, request_id);
                fieldTemplates[i] = templateData;
                i++;
            }
        }
        let fieldTemplatesNew = []
        let ids = new Set();
        fieldTemplates.forEach(innerArray => {
            let obj = innerArray[0];
            if (!ids.has(obj.id)) {
                fieldTemplatesNew.push(obj);
                ids.add(obj.id);
            }
        });
        let QuestionTemplateId = await Client.getQuestionnairTemplatesRfq(request_id)


        let QuestionTemplates = []
        for (const row of QuestionTemplateId) {
            let questionnairIds = await OnboardWorkFlowQuestionnaires.getQuestionairebyStageId(row.stage_id);

            if (!empty(questionnairIds)) {
                let QuestionData = await OnboardWorkFlowStages.get_qns_formData_by_id(questionnairIds, 0, 0, 1, request_id);
                QuestionTemplates.push(QuestionData);

            }
        }
        let QuestionTemplatesNew = []
        ids = new Set();
        QuestionTemplates.forEach(innerArray => {
            let obj = innerArray[0];
            if (!ids.has(obj.id)) {
                QuestionTemplatesNew.push(obj);
                ids.add(obj.id);
            }
        });
        let signAgrementData = await Client.getAllSignAgrementsOfRfq(request_id)
        let allDataEmpty = true;
        if (!empty(signAgrementData) || !empty(QuestionTemplates) || !empty(fieldTemplates)) {
            allDataEmpty = false;
        }
        let portfolio = await OnboardWorkFlowStages.getPortfoliobypartnerid(0, 1, request_id)
        // console.log("###########",signAgrementData);
        let requestProposals = await RequestProposals.getAllPropsalsByRequestId(request_id, userId, userType)
        // let customData=await OnboardWorkFlowStages.getRfqData(request_id)
        let team_members = []
        if (!empty(result)) {
            res.send({
                status: 1, data: result
                , skill: serviceSkill,
                products: products,
                requestAcceptedPartners,
                updates,
                attachments,
                customerData,
                labourCostServices,
                requestServices,
                payments,
                materials,
                workflows,
                signAgrementData,
                fieldTemplates: fieldTemplatesNew,
                QuestionTemplates: QuestionTemplatesNew,
                allDataEmpty,
                portfolio,
                requestProposals,
                team_members,
                team,
                // customData,
                message: "Data fetched successfully"
            });
        }
        else {
            res.send({ status: 0, message: "Error in fetching requets by id" })
        }
    } catch (error) {
        console.log(error, 'error in get request by id')
        res.send({ status: 0, message: 'failed to get request by id' })
    }
}
const RFPById = async (req, res) => {
    try {

      
        let{ userId,orderId}=req.body
        id=orderId
        console.log("############Hifiiiiiiiii",userId);
        console.log("############orderId",orderId);
        let orderData = await Proposals.getCustomerOrderRequestId(id,userId)
        let order_id = orderData.id

        if (!empty(order_id)) {
            let results 
            let attachments =[]
            if(!empty(orderData.proposalId)){
                console.log("############Hifiiiiiiiii");
                results = await Proposals.getVendorOrderProductsbyId(orderData.proposalOrder)
            }
            else{
                 results = await Proposals.getCustomerOrderProductsbyId(order_id)
                }
            attachments = await Proposals.getRequestProposaAttachmentsbyId(orderId)
            
            // console.log("######Rewq", results);
            // console.log("######Rewqqqq", attachments);

            if (!empty(results)) {
                for (const product of results) {


                    product.services = [];
                }

                let community = []
                orderData['cust_product'] = results;
                res.send({ status: 1, data: orderData,attachments, community, message: "Data fetched successfully" });
            } else {
                let community = [];
                orderData['cust_product'] = [];
                res.send({ status: 1, data: orderData,attachments, community, message: "Data fetched successfully" });
            }

        } else {
            res.send({ status: 0, message: "Error fetching data" })
        }

    } catch (error) {
        console.log("errror"+error)
        res.send({ staus: 0, message: 'Internal server error'+error })
    }
}
const updateProposalData = async (req, res) => {
    try {
        const { values,taxCategory, userId, userType, request_id, address, allLocationSame, quotation } = req.body;
        console.log('valuesvaluesvalues', values)
        //   let attachments = await RequestPartner.fetchAllRequestAttachments(request_id);
        let currentTime = moment().unix()
        let currentDate = moment().unix()
        const skills = values.skills?.map(row => row.id)
        const workflow = values.workflow?.map(row => row.id)
        let submission_deadline = moment(values.start).unix()
        let participation_ends = moment(values.end).unix()
        let uploadedfile = values.files_upload||[]
        console.log('bshdfbgisdbgisfigb1uploadedfile',uploadedfile)
        let requestdata = {}
        let result = await Proposals.getAllProposals(request_id, userId, userType)
        result = result.data
        let orderId = values.order_id
        requestdata['name'] = values?.name,
        requestdata['description'] = values?.description,
        requestdata['markup_type'] = values?.markup_type?.id || 2,
        requestdata['services'] = skills,
        requestdata['workflows'] = workflow,
        requestdata['labour_cost_services'] = values.services,
        requestdata['labour_cost'] = values.labour_cost || 0,
        requestdata['project_type'] = values.project_type && values.project_type["id"] || 0
        requestdata['project_category'] = values.project_category && values.project_category["id"] || 0;
        requestdata['community'] = values.community && values.community["id"] || 0
        requestdata['submission_deadline'] = values.start ? moment(values.start).unix() : 0
        requestdata['is_location'] = allLocationSame
        requestdata['notes'] = values.notes || "",
        requestdata['quotation'] = quotation || 0
        console.log("#############RequestData", requestdata)
        if (values.end !== (undefined || null)) {
            requestdata['participation_ends'] = values.end ? moment(values.end).unix() : 0
        } else {
            requestdata['participation_ends'] = 0
        }
        requestdata['start_date'] = null
        // requestdata['subject']=values.subject,
        // requestdata['email_content']=values.email_content
        if (values.welcome_message == true) {
            requestdata['welcome_message'] = values.welcome_message
            if (values.subject !== (undefined || null)) {
                requestdata['subject'] = values.subject
            } else {
                requestdata['subject'] = null
            }
            if (values.email_content !== (undefined || null)) {
                requestdata['email_content'] = values.email_content
            } else {
                requestdata['email_content'] = null
            }
        } else {
            requestdata['welcome_message'] = false
        }
        requestdata['type'] = 2
        if (values.draft == true) {
            requestdata['status'] = values.draft
        } else {
            requestdata['status'] = 2
        }
        if (!empty(quotation) && quotation === 1) {
            requestdata['status'] = 8
            requestdata['quotation_status'] = 2
        }
        requestdata['added_by'] = userId,
        requestdata['timestamp'] = currentTime


        let updateReqID = await Proposals.updateRequets(request_id, requestdata);
        console.log("####Notification message", updateReqID);

        if(result){
            if (!empty(updateReqID)) {
                let deleteAttachment = await Proposals.deleteRequestProposalAttachmentById(request_id)
                // console.log('bshdfbgisdbgisfigb1uploadedfile',uploadedfile)
                if(deleteAttachment){
                    for (const row of uploadedfile) {
                    console.log('uploadedfile-name',row.url)
                    console.log('uploadedfile-name',row.name)
                    let approvedImage = {}
                    approvedImage.name = row.url ? row.url :row.name;
                    approvedImage.extension = row.type;
                    approvedImage.proposal_id =request_id
                    approvedImage.added_by = userId
                    approvedImage.timestamp = moment().unix()
                    let upload = await Proposals.addRequestProposaAttachments(approvedImage)
                    // let upload = await Proposals.updateRequestProposalAttachmentsByProposalId(request_id,approvedImage)
                    console.log('bshdfbgisdbgisfigb1',upload,request_id,updateReqID)
                    }
                }


            }
        }

        let orderData = {};
        orderData['total'] = (values.total && values.total > 0) ? values.total + (values.taxAmount || 0) : 0,
        orderData['tax_category'] = taxCategory || null
        orderData['tax_amount'] = values.taxAmount || 0
        // orderData['budget'] = values.budget;
        orderData['budget'] = (values.budget && values.budget > 0) ? values.budget + (values.taxAmount || 0) : 0,
        orderData['extra_discount'] = values.invoice_discount || 0;
        orderData['request_id'] = request_id;
        orderData['timestamp'] = currentTime;
        orderData['sub_total'] = values.total - (values.invoice_discount || 0);
        orderData['tax'] = 0;
        orderData['status'] = 1;

        let updatedOrderId = await Proposals.updateCustomerOrder(orderId, orderData);

        let requestProduct = {}
        console.log("#################Old order");
        let CustomerProductData = await Proposals.getCustomerOrderProductsbyId(orderId);
        console.log("#################Old order", CustomerProductData);
        let deletedCustomerProduct = await Proposals.deletedCustomerOrderProduct(orderId);
      
        console.log("#################orderDaata",values.products);
        for (let row of values.products) {

            let product_id = row.product_id ? row.product_id : row.id;
            let product_name = row.product_name ? row.product_name : row.name
            let price = row.product_price ? row.product_price||0 : row.price||0;
            let ret_price = row.product_retail_price ? row.product_retail_price||0 : row.retail_price||0;
            let markup = row.product_markup ? row.product_markup : row.markup;
            let product_qty = row.quantity ? row.quantity : 1;
            // let subTotal = row.product_sub_total;
            // let productTotal = row.product_sub_total;
            let rowTotal = row.markup_type == 1 ? price||0 : ret_price||0
            let subTotal = (rowTotal * product_qty * (row.locationQuantity || 1)) - (row.discount || 0);
            let productTotal = (rowTotal * product_qty * (row.locationQuantity || 1)) - (row.discount || 0);

            requestProduct['order_id'] = orderId;
            requestProduct['product_id'] = product_id;
            requestProduct['product_name'] = product_name;
            requestProduct['product_price'] = price||0;
            requestProduct['product_retail_price'] = row.markup_type == 1 ? price||0 : ret_price||0;
            requestProduct['product_markup'] = markup;
            requestProduct['product_qty'] = product_qty;
            requestProduct['location_quantity'] = row.locationQuantity || 1,
                requestProduct['product_sub_total'] = subTotal;
            requestProduct['product_tax'] = 0;
            requestProduct['workflow'] = row.workflow,
                requestProduct['product_total'] = productTotal||0;
            requestProduct['discount'] = row.discount || 0;
            requestProduct['timestamp'] = currentTime;
            requestProduct['status'] = row.status;

            let requestProductResult = await Proposals.createCustomerOrderProduct(requestProduct);
            
        }
        console.log('values?.materials row')
        for (let row of values?.materials) {
            console.log('values?.materials row 2', row)

            let product_id = row.product_id ? row.product_id : row.id;
            let product_name = row?.product_name ? row.product_name : row?.name
            let price = row.product_price ? row?.product_price||0 : row?.price||0;
            let ret_price = row?.product_retail_price ? row?.product_retail_price||0 : row?.retail_price||0;
            let markup = row?.product_markup ? row?.product_markup : row?.markup;
            let product_qty = row?.quantity ? row?.quantity : 1;
            // let subTotal = row.product_sub_total;
            // let productTotal = row.product_sub_total;
            let rowTotal = row?.markup_type == 1 ? price||0 : ret_price||0
            let subTotal = (rowTotal * product_qty * (row?.locationQuantity || 1)) - (row?.discount || 0);
            let productTotal = (rowTotal * product_qty * (row?.locationQuantity || 1)) - (row?.discount || 0);

            requestProduct['order_id'] = orderId;
            requestProduct['product_id'] = product_id;
            requestProduct['product_name'] = product_name;
            requestProduct['product_price'] = price||0;
            requestProduct['product_retail_price'] = row.markup_type == 1 ? price||0 : ret_price||0;
            requestProduct['product_markup'] = markup;
            requestProduct['product_qty'] = product_qty;
            requestProduct['location_quantity'] = row.locationQuantity || 1,
                requestProduct['product_sub_total'] = subTotal;
            requestProduct['product_tax'] = 0;
            requestProduct['workflow'] = row.workflow,
                requestProduct['product_total'] = productTotal||0;
            requestProduct['discount'] = row.discount || 0;
            requestProduct['timestamp'] = currentTime;
            requestProduct['status'] = row.status;
            requestProduct['material'] = 1

            let requestProductResult = await Proposals.createCustomerOrderProduct(requestProduct);
            console.log('requestProductResult materials', requestProductResult)
        }
        let deleteServices = await Proposals.deleteRequestServices(request_id)
        console.log("selected servui", values.selectedServices);
        for (const row of values.selectedServices) {
            let rowQuantity = row.quantity ? row.quantity : 1;
            requestProduct['request_id'] = request_id
            requestProduct['labour_cost_service_id'] = row.labour_cost_service_id || row.id,
                requestProduct['recipe_id'] = row.recipe_id || null,
                requestProduct['product_id'] = row.product_id || null,
                requestProduct['qty'] = rowQuantity,
                requestProduct['unit_cost'] = row.unit_cost || row.total_cost,
                requestProduct['markup'] = row.markup,
                requestProduct['total_cost'] = row.total || (requestProduct['unit_cost'] * requestProduct['qty'])

                requestProduct['jobcost_unit_cost'] = row.unit_cost || row.total_cost || 0;
                requestProduct['jobcost_quantity'] = rowQuantity || 0;
                requestProduct['jobcost_total_cost'] = requestProduct['jobcost_unit_cost'] * requestProduct['jobcost_quantity']

            let response = await Proposals.addRequestServices(requestProduct)
        }
        // let existingPartners=await RequestProposals.getAllPropsalsByRequestId(request_id,1,1)
         // if (partnerData && partnerData.length > 0) {
        //     console.log("#########PartnerData",partnerData);
        //     let client = {}
        //     let insertedstatus = null
        //     let currentPartnerIds = new Set(partnerData.map(partner => partner.user_id));
        //     for (let eachPartner of existingPartners) {
        //         if (!currentPartnerIds.has(eachPartner.user_id)) {
        //             await Proposals.removeRequestPartner(eachPartner.partnerId, request_id);
        //         }
        //     }
        

            
        //     for (let eachPartner of partnerData) {
             
        //         client['request_id'] = request_id,
        //             client['last_seen'] = currentDate,
        //             client['timestamp'] = currentDate,
        //             client['added_by'] = userId,
        //             client['partner_id'] = eachPartner.id
        //         client['accept_status'] = 1;
        //         client['status'] = 1
        //         let existingPartner = existingPartners.find(partner => partner.vendor_id === eachPartner.user_id);
                
        //         if(!empty(existingPartner)){
        //             insertedstatus = await Proposals.addRequestPartners(client)
        //         }
                
               
        //     }


        // }
        // console.log("existingPartners", existingPartners);
         let deletePartners = await Proposals.deleteProposalPartners(request_id)
        let partnerData = values.clients
         if (partnerData && partnerData.length > 0) {
                console.log("#########PartnerData",partnerData);
                let client = {}
               
                
                for (let eachPartner of partnerData) {
                 
                    client['request_id'] = request_id,
                        client['last_seen'] = currentDate,
                        client['timestamp'] = currentDate,
                        client['added_by'] = userId,
                        client['partner_id'] = eachPartner.id
                    client['accept_status'] = 1;
                    client['status'] = 1
                    // let existingPartner = existingPartners.find(partner => partner.vendor_id === eachPartner.user_id);
                    
                    // if(!empty(existingPartner)){
                        insertedstatus = await Proposals.addRequestPartners(client)
                    // }
                    
                   
                }
    
    
            }
       

        // let NewCustomerProductData = await Proposals.getCustomerOrderProductsbyId(orderId);
        // console.log("#################Old order", NewCustomerProductData);
        if (updateReqID) {
            let notification_msg = ``
            console.log("####Notification messages", notification_msg);
            let notification_url = `official-request/view/${request_id}`
            console.log("############name", result[0]['name']);
            console.log("############name", requestdata['name']);
            if (result[0]['name'] != requestdata['name']) {
                notification_msg += `The RFQ Name changed to <strong> ${requestdata['name']}.</strong> `
            }
            if (result[0]['description'] != requestdata['description']) {
                notification_msg += `The RFQ description updated to <strong> ${requestdata['description']}.</strong> `
            }
            if (result[0]['project_type'] != requestdata['project_type']) {
                notification_msg += `The RFQ Project type has been updated to <strong> ${values?.project_type['name']}.</strong> `
            }
            if (result[0]['project_category'] != requestdata['project_category']) {
                notification_msg += `The RFQ Project category has been updated to <strong> ${values.project_category['name']}.</strong> `
            }
            if (result[0]['community'] != requestdata['community']) {
                notification_msg += `The RFQ Community has been updated to <strong> ${values.community.name}.</strong> `
            }

            if (result[0]['submission_deadline'] != requestdata['submission_deadline']) {
                notification_msg += `The RFQ Start date has been updated to <strong> ${moment(requestdata['submission_deadline'] * 1000).format('YYYY-MM-DD ')}.</strong> `
            }
            if (result[0]['participation_ends'] != requestdata['participation_ends']) {
                notification_msg += `The RFQ End date has been updated to <strong> ${moment(requestdata['participation_ends'] * 1000).format('YYYY-MM-DD ')}.</strong> `
            }
            console.log("#######Updated RowsCheck", notification_msg);
            // CustomerProductData?.forEach(oldItem => {
            //   const newItem = NewCustomerProductData.find(item => item.product_id === oldItem.product_id);
            //   if (!newItem) {
            //     notification_msg += `Product '${oldItem.product_name}' removed from the request.`;
            //   }
            //   else if (newItem.quantity !== oldItem.quantity) {
            //     notification_msg += `Quantity of '${oldItem.product_name}' changed from ${oldItem.quantity} to ${newItem.quantity}.`;

            //   }
            //   if (JSON.stringify(newItem.location) !== JSON.stringify(oldItem.location)) {
            //     notification_msg += `Location for product '${oldItem.product_name}' changed.`;
            //   }
            // });
            // NewCustomerProductData.forEach(newItem => {
            //   const oldItem = CustomerProductData.find(item => item.product_id === newItem.product_id);
            //   if (!oldItem) {
            //     notification_msg += `New product '${newItem.product_name}' added to the order.`;
            //   }
            // });
            console.log("#######Updated Rows", notification_msg);
            if (!empty(notification_msg)) {
                let requestActivity = {}
                requestActivity['request_id'] = request_id;
                requestActivity['activity'] = notification_msg;
                requestActivity['added_by'] = userId
                requestActivity['timestamp'] = currentTime
                //   let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            }

        }
        let requestDetails = await Proposals.getRequestById(request_id)

        if (!empty(requestDetails[0].status)) {
            let notification_msg = `The RFQ <strong> ${requestDetails[0]['name']}.</strong> has been updated`
            let notification_url = `official-request/view/${request_id}`

            let requestPartners = await Proposals.getRequestPartnersByIds([], request_id)

            for (let eachpartner of requestPartners) {
                //alert 
                let incrementResult = await Admin.incrementField(eachpartner.id, "noti_count", 1);
                let notificationUser = {
                    user_id: eachpartner.id,
                    url: notification_url,
                    timestamp: currentTime,
                    message: notification_msg,
                    status: 1,
                    from_id: userId,
                }
                const addNotificationResult = await Admin.addNotification(notificationUser);
            }
            // let requestTeamuserId = await Request.getRequestTeamUserIds(request_id)
            // for (let request_team_us_id of requestTeamuserId) {
            //   // Alert assigned user of updation
            //   let incrementResult = await Admin.incrementField(request_team_us_id, 'noti_count', 1)
            //   let addNotification = {
            //     user_id: request_team_us_id,
            //     url: notification_url,
            //     timestamp: currentTime,
            //     message: notification_msg,
            //     status: 1,
            //     from_id: userId,
            //   }
            //   const addNotificationResult = await Admin.addNotification(addNotification);
            // }
            const adminIds = await Admin.getAllAdminIds()
            for (let eachadminIds of adminIds) {
                let incrementResult = await Admin.incrementField(eachadminIds, 'noti_count', 1)
                let addNotification = {
                    user_id: eachadminIds,
                    url: notification_url,
                    timestamp: currentTime,
                    message: notification_msg,
                    status: 1,
                    from_id: userId,
                }
                const addNotificationResult = await Admin.addNotification(addNotification);
            }
            // let requestActivity = {}
            // requestActivity['request_id'] = request_id;
            // requestActivity['activity'] = notification_msg;
            // requestActivity['added_by'] = userId
            // requestActivity['timestamp'] = currentTime
            // let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            res.send({ status: 1, message: 'Request updated successfully' })
        } else {
            res.send({ message: 'failed to edit request' })
        }
    } catch (error) {
        console.log(error, 'error in get request by id')
        res.send({ status: 0, message: 'failed to get request by id1' + error })
    }
}
const deleteProposalById = async (req, res) => {
    try {
      const { request_id, } = req.body;
      let result = await Proposals.deleteProposalById(request_id)
      if (result) {
        res.send({ status: 1, data: result, message: 'Proposal deleted successfully' })
      } else {
        res.send({ status: 0, message: 'Proposal deleted failed' })
      }
    } catch (error) {
      console.log(error, 'error in delete request')
      res.send({ status: 0, message: 'failed to delete request' })
    }
  }

  const saveProposalOrder = async (req, res) => {
    try {
      const { reorderedItems } = req.body;
      console.log("updatedCardsupdatedCardsupdatedCards",reorderedItems)
      await Proposals.updateCardOrder(reorderedItems);
      res.status(200).send({ status: 1, message: 'Order saved' });
    } catch (error) {
      console.log('saveReq error : ',error)
      res.status(500).send({ status: 500, message: 'Error saving order', error:error });
    }
  }
module.exports = { getAllProposals, addRfp, getProposalById, RFPById, updateProposalData,deleteProposalById ,saveProposalOrder}