const sgMail = require('@sendgrid/mail')
const { SENDGRID_API_KEY, BASE_URL, portalName } = require("../constants/constant")
const { sendPartnerMail, activateProfile } = require("../constants/emailTemplates");
const Admin = require ('../models/admin')
const Request = require ('../models/request')
const moment = require("moment");
const crypto = require("crypto");
const sequelize = require("../config/dbconnection");
const { empty, arrayDiffAssoc } = require('../Helpers/Common');
const Driver = require('../models/driver')
const installationModel = require('../models/installation')
const Vehicle = require('../models/vehicle')
const Route = require('../models/routes')
const Project = require('../models/Projects')
const Installation = require('../models/installation')
const Product = require('../models/product')
let currentDate = Math.round(moment().valueOf() / 1000);
const admin = require('firebase-admin');


// admin.initializeApp({
//     credential: admin.credential.cert(serviceAccount),
//     databaseURL: "https://notification-db426.firebaseio.com",
//   });



const createRoute=async(req,res)=>{
    try {
        const {routeName,zipcodes,userId,description,community_id,client_id} = req.body
        let data={}
        data['name'] = routeName
        data['zipcodes'] = zipcodes.join(', ')
        data['description'] = description
        data['assigned_driver'] = null
        data['timestamp'] = currentDate
        data['added_by'] = userId
        data['client_id'] = client_id
        data['community_id'] = community_id
        data['status'] = 1
        const randomBytes = crypto.randomBytes(2).toString('hex');
        const u_id = parseInt(randomBytes, 16) % 90000 + 10000;
        data['unique_id'] = 'SWS'+u_id
        data['type'] = 2
        let result = await Route.createRoute(data)
        if(!empty(result)){
            res.send({
                status:1,message:'Route added successfully'
            })
        }else{
            res.send({
                status:0,message:'Failed to add Route'
            })
        }
    } catch (error) {
        console.log(error)
    }
}

const getAllRoutes=async(req,res)=>{
    try {
        const {userId,userType,rowPerpage,page,searchData, whereCondition,filterProjectType} = req.body
        let data=[]
        // if(userType===1){
            data = await Route.getAllRoutes(rowPerpage,page,searchData, whereCondition,filterProjectType)
            if(!empty(data)){
                res.send({
                    status:1,data
                })
            }
        // }
    } catch (error) {
        console.log(error)
    }
}

const getAllUnAssignedRoutes=async(req,res)=>{
    try {
        let data=[]
        data = await Route.getAllUnAssignedRoutes()
         if(!empty(data)){
             res.send({ status:1,data })
        }
    } catch (error) {
        console.log('Get All UnAssigned Routes error : ',error)
    }
}

const updateRoute=async(req,res)=>{
    try {
        const {routeName,zipcodes,userId,id,description,client_id,community_id} = req.body
        let data={}
        data['name'] = routeName
        data['zipcodes'] = zipcodes.join(', ')
        data['description'] = description
        data['client_id'] = client_id
        data['community_id'] = community_id
        data['timestamp'] = currentDate
        let result =await Route.updateRoute(data,id)
        if(result){
            res.send({
                status:1,message:`Route ${data['name']} has been updated successfully !`
            })
        }else{
            res.send({
                status:0,message:`Failed to update the route`
            })
        }
    } catch (error) {
        console.log(error)
    }
}

const deleteRoute=async(req,res)=>{
    try {
        const {id,status} = req.body
        let data={}
        data['status'] = status
        let result =await Route.updateRoute(data,id)
        if(result){
            res.send({
                status:1,message:`Route has been deleted  successfully !`
            })
        }else{
            res.send({
                status:0,message:`Failed to delete the route`
            })
        }
    } catch (error) {
        console.log(error)
    }
}

const getRouteDataById=async(req,res)=>{
    try {
        const {id} = req.body 
        let data = await Route.getRouteDatabyId(id)
        if(!empty(data)){
            res.send({
                status:1,data
            })
        }else{
            res.send({
                status:0
            })
        }
    } catch (error) {
        console.log(error)
    }
}

const getInstallationsByRoute = async (req,res) =>{
    try{
        const {id,zipcodes,driver,status} = req.body
     
        let installationData = [];
        const zipcodesArray = zipcodes?.split(",").map(zipcode => zipcode.trim());
        console.log('driverIddriverId',req.body)

        // Function to fetch attachments for each installation
        const fetchAttachments = async (installation) => {
            const attachmentResult = await sequelize.query(
                `SELECT ra.*, CONCAT(u.first_name,' ',u.last_name) AS approved_by_name 
                    FROM request_attachments ra
                    LEFT JOIN users u ON u.id = ra.approved_by
                    WHERE ra.status = :status 
                    AND ra.approved = :approved 
                    AND (ra.file_type LIKE 'image/%' OR ra.file_type = :imgType) 
                    AND ra.request_id = :requestId 
                    AND FIND_IN_SET(:locationId, ra.location_ids)`,
                    // AND FIND_IN_SET(:productId, ra.product_ids)
                {
                    type: sequelize.QueryTypes.SELECT,
                    replacements: {
                        status: 1,
                        approved: 1,
                        imgType: 'img',
                        requestId: installation.request_id,
                        // productId: installation.customer_order_product_id,
                        locationId: installation.location_id,
                    }
                }
            );

            installation.attachments = attachmentResult.length > 0 ? attachmentResult : [];
            return installation;
        };

        // Function to fetch installations and their attachments
        const fetchInstallations = async (installations) => {
            return installations?.length > 0
                ? await Promise.all(installations.map(fetchAttachments))
                : [];
        };

        if(zipcodesArray?.length > 0 && driver.length==0){
            for (const zipcode of zipcodesArray) {
                let data = await Route.getInstallationByZipcode(zipcode)
                console.log('datadatadatadatadatazipcodes',data)

                let installationsWithAttachments = await fetchInstallations(data);
                installationData.push(...installationsWithAttachments);
            }
            res.send({ status:1, message:'Installations fetched successfully',data:installationData })
        }else if(driver && driver.length >0 ){
            for (const data1 of driver) {
                let data = await Route.getInstallationByDriverId(data1.id,status?.status)
                console.log('datadatadatadatadatadriverdriver',data)

                let installationsWithAttachments = await fetchInstallations(data);
                installationData.push(...installationsWithAttachments);
            }
            res.send({ status:1, message:'installations found',data:installationData })
        }else if(status && driver.length ==0){
            let data = await Route.getInstallationByStatus(status?.status)
            console.log('datadatadatadatadatadriverstatus',data)

            let installationsWithAttachments = await fetchInstallations(data);
            installationData.push(...installationsWithAttachments);

            res.send({ status:1, message:'installations found',data:installationData })
        }else{
            res.send({ status:0, message:'No installations found' })
        }
    }catch(error){
        console.log('Error : ',error);
    }
}

const assignInstallationToDriver = async (req,res) => {
    try {
        const {routeId,routeName,driverId,userId,installationId,driverData} = req.body
        let currentDate = Math.round(moment().valueOf() / 1000);
        let data={}
        data['route_id'] = routeId
        // data['driver_id'] = driverId
        data['driver_id'] = driverData.map(driver => driver.id).join(",")
        data['status'] = 6
        let updationResult=[]
        for(const id of installationId){
            let result =await installationModel.updateInstallationStatus(data,id)
            let installationData = await installationModel.fetchApointmentById(id)

            console.log("installationDataaaaaaaaaaaaaaaaaaaaa",installationData);
            
            if(installationData?.length > 0){
                if(installationData[0]?.fcmToken){
                    console.log(installationData[0].fcmToken,"fcmTokennnnnnnnnnnn");

                        const message = {
                            data: {
                                // Your custom data payload if needed
                                // Example:
                                score: '850',
                                time: '2:45'
                            },
                            notification: {
                                title: 'Installation',
                                body: `A new installation ${installationData[0].name} has been assigned`
                            },
                            token: installationData[0].fcmToken // Add registration tokens of specific devices here
                        };


                        admin.messaging().send(message)
                        .then((response) => {
                        console.log('Successfully sent message:', response);
                    // Assuming 'res' is used to respond to an HTTP request
                        res.send({ success: true, response });
                        })
                        .catch((error) => {
                        console.error('Error sending message:', error);
                    res.status(500).send({ error: error.message });
                    });
                }
                let installation = installationData[0]
                // Notification
                let notificationMsg = `Installation ${installation.name} has been assigned to ${installation.driver_name}.`;
                let notificationUrl = "installation";
                let notificationData_user = {
                    user_id:userId,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: userId
                }
                const addNotificationResult_user = await Admin.addNotification( notificationData_user );
                let adminIds = await Admin.getAllAdminIds();
                let notificationData = {};
                for (const adminId of adminIds) {
                    if (adminId != userId) {
                    const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);
                    notificationData = {
                        user_id: adminId,
                        url: notificationUrl,
                        timestamp: currentDate,
                        message: notificationMsg,
                        status: 1,
                        from_id: userId,
                    };
                    const addNotificationResult = await Admin.addNotification( notificationData );    
                    }
                }
            }
            updationResult.push(result)
        }

       


        if(updationResult?.length === installationId?.length){
            res.send({ status:1,message:`Route ${routeName} has been assigned successfully !` })
        }else{
            res.send({ status:0,message:`Failed to assign the route` })
        }
    } catch (error) {
        console.log(error)
        res.send({ status:500,message:`Error assigning the route` })
    }
}

const addSelectedRoutes=async(req,res)=>{
    try {
        const {route,isInstaller,userId} = req.body

        // console.log('routerouteroute 1',req.body)
        // console.log('routerouteroute 2',route)

        const routeData=route.routeData
        let overallStatus = 1;
        for(let eachdata of routeData){
            let data={}
            data['driver_id']= eachdata.driver_id
            data['route_id'] = eachdata.route_id
            data['installation_id'] = eachdata.id
            data['installler_id'] = isInstaller? userId : null
            data['status'] =0
            let result = await Route.addDriverSelectedRoutes(data)
            if (result ) {
                overallStatus = 1
              }else{
                overallStatus = 0
              }
        }
        res.status(200).send({ status: overallStatus });
    } catch (error) {
        console.log(error)
    }
}

const updateRouteStatus=async(req,res)=>{
    try {
        const {id,status} = req.body
        let data={}
        data['status'] = status
        let result =await Route.updateStatusByInstallationId(id,status)
        console.log("result",result)
        if(result){
            res.send({
                status:1,message:`Route ${data['status']} has been updated successfully !`
            })
        }else{
            res.send({
                status:0,message:`Failed to update the route`
            })
        }
    } catch (error) {
        console.log(error)
    }
}

const deleteCompletedRoute=async(req,res)=>{
    try {
        const {id} = req.body
      
        let result =await Route.findByDriverIdAndDeleteIfStatus1(id)
        if(result){
            res.send({
                status:1,message:`Route has been deleted  successfully !`
            })
        }else{
            res.send({
                status:0,message:`Failed to delete the route`
            })
        }
    } catch (error) {
        console.log(error)
    }
}


const findDataByDriverId=async(req,res)=>{
    try {
        const {id,isInstaller,userId} = req.body
      
        console.log('resultresultresult 1',req.body)
        let result =await Route.findByDriverId(id,isInstaller,userId)
        console.log('resultresultresult 2',result)
        if(result){
            res.send({
                status:1,message:`data fetched  successfully !`,result:result
            })
        }else{
            res.send({
                status:0,message:`Failed to delete the route`
            })
        }
    } catch (error) {
        console.log(error)
    }
}


const demoMessage=(req,res)=>{
    // const registrationToken = "eloeZNzIQCGjN5Km2_VDxE:APA91bFw9TqKhTBj2QD6zfVKmmkYoPmgrlmaRYAR0ECuW5fLYbspVh3sImFMkEr2PPh1FNjMpymjU71MR-si4FTaj8WGrrx7OKXfO0_Sdb1JmmZ0N0jy40xdr-3psPJb7qBq5XeCACvm";
    // const registrationToken = "eAEkVW2aRrORZF9q7jJ1UY:APA91bHlXZErFmlES-NzaKbthH402qJq0wd8fTE2sz2Let9vdXuXw7EOd6-30Hrm4hAZze1BOk3cll8tpF0ohdK-pH-y0MJoeLr420f31-sSD4y9XEels-ZVMHuxWFNF9MnSsKQVy_5W";
    const registrationToken="fjAOiSzRQb2UBRq4kNGQEI:APA91bFFts6XsZ2suBygCW4eTeIFchJhWXTdYg156j-HM8kxmnZqIzxlp_VZZd2AeD0EclqICFJEOv0WFjy7tpXRi_OU85irUMm3BKh6IDWW5NXjTI_vnyLBtyYl_YNCwuM2lnv8Bvts"
    const message = {
        data: {
            // Your custom data payload if needed
            // Example:
            score: '850',
            time: '2:45'
        },
        notification: {
            title: 'signwise : Hello',
            body: 'hello hi '
        },
        token: registrationToken  
    };


    admin.messaging().send(message)
     .then((response) => {
      console.log('Successfully sent message:', response);
   // Assuming 'res' is used to respond to an HTTP request
     res.send({ success: true, response });
  
      })
     .catch((error) => {
       console.error('Error sending message:', error);
   res.status(500).send({ error: error.message });
 });

}


const getAllAssignedRoutes=async(req,res)=>{
    try {
        let =[]
        data = await Route.getAllAssignedRoutes()

        console.log('datadatadatadatadata',data)
         if(!empty(data)){
             res.send({ status:1,data })
        }
    } catch (error) {
        console.log('Get All UnAssigned Routes error : ',error)
    }
}

const assignTSJobToRoute=async(req,res)=>{
    try {
        const {selectedRoute, selectedSalesOrder, selectedDriver,selectedTeam,isDriver,selectTemplate,previosSalesOrderId,userId} = req.body
        let currentDate = Math.round(moment().valueOf() / 1000);

        // console.log('daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',req.body)
        if(previosSalesOrderId && (previosSalesOrderId != selectedSalesOrder.requestId)){
            const installationData = await Installation.findInstallationDataByRequestId(previosSalesOrderId)
        // console.log('installationData',installationData)

        const installationTableData = {
            installation_temp_id :null,
            status : 1,
            team_id :null,
            driver_id :  null,
            route_id : null
          }
           const updateInstallation = await Installation.updateInstallationDataByRequestId(previosSalesOrderId,installationTableData)

        }
        
              const installationData = await Installation.findInstallationDataByRequestId(selectedSalesOrder.requestId)
        // console.log("installationData",installationData)
        // return

        if(selectedTeam && !selectedTeam.user_id){
            res.send({ status:3,message:'Unable to assign installer userId missing' })

        }

        let data={};
        data['assigned_sales_order'] = selectedSalesOrder.requestId
        data['assigned'] = 1
        data['assigned_driver'] =  isDriver ?selectedTeam.id : selectedDriver.map(driver => driver.id).join(",") || null,
        data['zipcodes'] = installationData.map(data => data?.zipcode).join(', ');
        let result =await Route.updateRoute(data,selectedRoute)

        // console.log('resultresultresult',result,data)
     
        const installationTableData = {
            installation_temp_id :selectTemplate.id,
            // status : (routeId) ? 6 : 1,
            status : (selectedRoute) ? 2 : 1,
            team_id : selectedTeam?.user_id||selectedTeam.map(driver => driver.user_id).join(","),
            driver_is_installer : isDriver ? 2 : 1,
            driver_id : isDriver ?selectedTeam.id : selectedDriver.map(driver => driver.id).join(",") || null,
            route_id : selectedRoute || null
          }
           const updateInstallation = await Installation.updateInstallationDataByRequestId(selectedSalesOrder.requestId,installationTableData)
          
        let driverId =isDriver ?selectedTeam.id : selectedDriver.map(driver => driver.id).join(",") || null

//notification
      try {
        let notificationMsg=`A new Installation ${installationData[0]?.name} has been assigned to ${installationData[0]?.driver_name}`
        let mobileNotification=`A new Installation ${installationData[0]?.name} has been assigned to you`

         let notificationUrl = "installation";
                let notificationData_user = {
                    user_id:userId,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: userId
                }
                const addNotificationResult_user = await Admin.addNotification( notificationData_user );

                      if(installationData[0]?.fcmToken){
                          const message = {
                            data: {
                                // Your custom data payload if needed
                                // Example:
                                score: '850',
                                time: '2:45'
                            },
                            notification: {
                                title: 'Installation',
                                body: mobileNotification || `Installation status has been updated.`
                            },
                            token: installationData[0]?.fcmToken // Add registration tokens of specific devices here
                          };
                    
                    
                          admin.messaging().send(message)
                              .then((response) => {
                              console.log('Successfully sent message:', response);
                            // Assuming 'res' is used to respond to an HTTP request
                              res.send({ success: true, response });
                              })
                              .catch((error) => {
                                console.error('Error sending message:', error);
                            res.status(500).send({ error: error.message });
                          });
                        }
        
      } catch (error) {
        console.log('error on sending notification')
      }

        if(!empty(updateInstallation)){
            res.send({ status:1,message:'Updated successfully' })
        }else{
            res.send({ status:0,message:'Failed to update' })
        }
    } catch (error) {
        console.log('assignTSJobToRoute error : ',error)
        res.send({ status:500, message:'Server error',error:error })
    }
}

const fetchAllUnassignedSalesorderFromAppointments=async(req,res)=>{
    try {
        const userId = req.body.userId.value
        const userType = req.body.userType.value
        const hasPermission = req.body.hasPermission || false
        const routeId = req.body.routeId || null
        let appointments=await Route.fetchAllUnassignedSalesorderFromAppointments(userId,userType,hasPermission,routeId);
        let results = await Project.getAllProjects(hasPermission, true, userType, userId,null,'new',null,null,false);
        let allInstalation = await Route.fetchAllUnassignedSalesorderFromAppointments(userId, userType, hasPermission,routeId);
        let filteredProjects = results.filter(project => {
        return !allInstalation.some(installation => installation.project_id === project.id);
        });
        let request = false;
        let projectTasks = await Promise.all(
        filteredProjects.map(async (data) => {
            const id = data.id
            let productOrServiceData = [];
            let result = await Project.findProjectById(id,request);
            if (result.project_category == 11) {
                productOrServiceData = await Installation.getServices(result.request_id);
                for (let service of productOrServiceData) {
                let locationdata = await Installation.getServiceLocations(service.id, result.request_id);
                service.locationdata = locationdata;
                }
            } else {
                productOrServiceData = await Installation.getProducts(result.order_id);
                for (let product of productOrServiceData) {
                let locationdata = await Installation.getLocations(product.id, product.product_id);
                product.locationdata = locationdata;
                }
            }
            for (let data of productOrServiceData) {
                let locationData = data.locationdata;
                for (let i = 0; i < locationData.length; i++) {
                data.address = locationData[i].address;
                data.city = locationData[i].city;
                data.state = locationData[i].state;
                data.zipcode = locationData[i].zip;
                data.name = result.name;
                data.project_id = result.id;
                data.request_id = result.request_id;
                data.product_id = data?.product_id;
                data.labour_cost_service_id = data?.labour_cost_service_id;
                data.location_id = locationData[i].id;
                data.start_date = result.start_date;
                data.installation_date = result.installation_date;
                data.due_date = result.installation_date;
                data.location_quantity = locationData[0]?.location_quantity || 1;
                }
            }
            return productOrServiceData;
        })
        );
        projectTasks = projectTasks.flat();
        res.send({ status:1,appointments,userType,userId,filteredProjects : projectTasks })
    } catch (error) {
        console.log('Get All UnAssigned Sales Order error : ',error)
        res.send({ status:500,message:'Server Error', error:error })
    }
}

const saveTSRouteLocations = async (req, res) => {
    try {
        const { selectedRoute, addedLocations, selectedProducts, userId } = req.body;
        let currentDate = Math.round(moment().valueOf() / 1000);
        
        // Fetch route data
        const routeData = await Route.getRouteDatabyId(selectedRoute);
        const routeProductsData = await Route.fetchRouteProductsByRouteId(selectedRoute);
        if (routeProductsData) {
            await Route.deleteRouteProductsByRouteId(selectedRoute);
        }
        // Fetch old route locations before deleting
        const oldRouteLocations = await Route.fetchRouteLocationsByRouteId(selectedRoute);
        if (oldRouteLocations) {
            await Route.deleteRouteLocationsByRouteId(selectedRoute);
        }

        let savedProducts = [];
        let savedLocations = [];
        let locationMapping = {};

        if (selectedProducts && selectedProducts?.length > 0) {
            for (let loc of selectedProducts) {
                const productData = {
                    route_id: selectedRoute,
                    product_id: loc.id,
                    qty: loc.qty || 0,
                    status: 1,
                    color:loc.color
                };
                const saveProduct = await Route.addRouteProducts(productData);
                if (addedLocations && addedLocations.length > 0) {
                    const filteredAddedLocations = addedLocations?.filter((item)=>item.productId == loc.id)
                    for (let oldLoc of filteredAddedLocations) {
                        console.log('oldLoc', oldLoc)
                        const locationData = {
                            route_id: selectedRoute,
                            route_product_id: saveProduct,
                            city: oldLoc.city || null,
                            address: oldLoc.address || null,
                            state: oldLoc.state || null,
                            zip: oldLoc.zip || null,
                            wholeAddress: oldLoc.wholeAddress || null,
                            latitude: oldLoc.lat || null,
                            longitude: oldLoc.lng || null,
                            timestamp: currentDate,
                            added_by: userId,
                            status: 1,
                            starting_point: oldLoc.starting_point || null,
                            ending_point: oldLoc.ending_point || null,
                            index_order: oldLoc?.index || null,
                            color: oldLoc?.color || null,
                        };
                
                        const saveLocation = await Route.addRouteLocations(locationData);
                        if (saveLocation) {
                            savedLocations.push(saveLocation);
                            if(routeData?.[0]?.assigned_sales_order){
                                locationMapping[oldLoc.location_id] = saveLocation;
                            }
                        }
                    }
                }

                if (saveProduct) {
                    savedProducts.push(saveProduct);
                }
            }
        }

        if(routeData?.[0]?.assigned_sales_order){
            for (const [oldId, newId] of Object.entries(locationMapping)) {
                let updateData = {
                    route_location_id: newId
                };
                console.log('routeData---updateData', updateData)
                console.log('routeData---oldId', oldId)
                await Request.updateLocation(updateData, oldId);
            }            
        }

        if (savedLocations?.length > 0 && savedProducts?.length > 0) {
            const notificationMsg = `Products and Locations saved successfully for route ${routeData?.[0]?.name}`;
            const notificationUrl = "routes";
            const notificationData_user = {
            user_id: userId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId,
            };
    
            // Send notification
            const addNotificationResult_user = await Admin.addNotification(notificationData_user);
            if (addNotificationResult_user) {
            return res.send({ status: 1, message: 'Products and Locations saved successfully', locationMapping, savedLocations, savedProducts, locationMapping  });
            } else {
            return res.send({ status: 0, message: 'Failed to save products and locations', newMessage: 'Failed to send notification' });
            }
        } else {
            return res.send({ status: 0, message: 'Failed to save products and locations' });
        }
    } catch (error) {
      console.error('saveTSRouteLocations error:', error);
      return res.send({ status: 500, message: 'Server error', error: error.message });
    }
};

// const saveTSRouteLocations = async (req, res) => {
//     try {
//         const { selectedRoute, addedLocations, selectedProducts, userId } = req.body;
//         let currentDate = Math.round(moment().valueOf() / 1000);
        
//         // Fetch route data
//         const routeData = await Route.getRouteDatabyId(selectedRoute);
//         const routeProductsData = await Route.fetchRouteProductsByRouteId(selectedRoute);
        
//         // Fetch existing route locations (before deleting)
//         const existingRouteLocations = await Route.fetchRouteLocationsByRouteId(selectedRoute);
        
//         // Delete old products (but keep locations for reference)
//         if (routeProductsData) {
//             await Route.deleteRouteProductsByRouteId(selectedRoute);
//         }

//         let savedProducts = [];
//         let savedLocations = [];
//         let locationIdMap = {}; // Store old location IDs for reference

//         if (selectedProducts && selectedProducts.length > 0) {
//             for (let product of selectedProducts) {
//                 const productData = {
//                     route_id: selectedRoute,
//                     product_id: product.id,
//                     qty: product.qty || 0,
//                     status: 1,
//                 };
//                 const saveProduct = await Route.addRouteProducts(productData);

//                 if (addedLocations && addedLocations.length > 0) {
//                     const filteredAddedLocations = addedLocations?.filter((loc) => loc.productId == product.id);

//                     for (let loc of filteredAddedLocations) {
//                         // Check if the location already exists
//                         const existingLocation = existingRouteLocations?.find(
//                             (oldLoc) => oldLoc.id === loc.id
//                         );

//                         let locationId = existingLocation ? existingLocation.id : null;

//                         const locationData = {
//                             route_id: selectedRoute,
//                             route_product_id: saveProduct,
//                             city: loc.city || null,
//                             address: loc.address || null,
//                             state: loc.state || null,
//                             zip: loc.zip || null,
//                             wholeAddress: loc.wholeAddress || null,
//                             latitude: loc.lat || null,
//                             longitude: loc.lng || null,
//                             timestamp: currentDate,
//                             added_by: userId,
//                             status: 1,
//                         };

//                         let saveLocation;
//                         if (locationId) {
//                             // Update existing location
//                             await Route.updateRouteLocation(locationId, locationData);
//                             saveLocation = locationId;
//                         } else {
//                             // Insert new location
//                             saveLocation = await Route.addRouteLocations(locationData);
//                         }

//                         if (saveLocation) {
//                             savedLocations.push(saveLocation);
//                             locationIdMap[`${loc.lat}-${loc.lng}`] = saveLocation;
//                         }
//                     }
//                 }

//                 if (saveProduct) {
//                     savedProducts.push(saveProduct);
//                 }
//             }
//         }

//         if (savedLocations?.length > 0 && savedProducts?.length > 0) {
//             const notificationMsg = `Products and Locations saved successfully for route ${routeData?.[0]?.name}`;
//             const notificationUrl = "routes";
//             const notificationData_user = {
//                 user_id: userId,
//                 url: notificationUrl,
//                 timestamp: currentDate,
//                 message: notificationMsg,
//                 status: 1,
//                 from_id: userId,
//             };

//             // Send notification
//             const addNotificationResult_user = await Admin.addNotification(notificationData_user);
//             if (addNotificationResult_user) {
//                 return res.send({
//                     status: 1,
//                     message: 'Products and Locations saved successfully',
//                     savedLocations,
//                     savedProducts,
//                     locationIdMap, // Returning old IDs of locations
//                 });
//             } else {
//                 return res.send({
//                     status: 0,
//                     message: 'Failed to save products and locations',
//                     newMessage: 'Failed to send notification',
//                 });
//             }
//         } else {
//             return res.send({ status: 0, message: 'Failed to save products and locations' });
//         }
//     } catch (error) {
//         console.error('saveTSRouteLocations error:', error);
//         return res.send({ status: 500, message: 'Server error', error: error.message });
//     }
// };

const fetchRouteLocationsByRouteId = async (req, res) => {
    try {
        const { selectedRoute,sales_order_id } = req.body;
        let routeData = await Route.fetchRouteLocationsByRouteId(selectedRoute);
        let productData = await Route.fetchRouteProductsByRouteId(selectedRoute,sales_order_id);

        if (Array.isArray(productData) && productData.length > 0 && sales_order_id) {
  const validRouteProductIds = new Set(productData.map(p => p.id));

  // Filter routeData where route_product_id exists in productData
  routeData = routeData.filter(r => validRouteProductIds.has(r.route_product_id));
}

        if (routeData || productData) {
            return res.send({ status: 1, message: 'Data fetched successfully', routeData:routeData, productData:productData });
        } else {
            return res.send({ status: 0, message: 'Failed to fetch locations and products' });
        }
    } catch (error) {
      console.error('fetchRouteLocationsByRouteId error:', error);
      return res.send({ status: 500, message: 'Server error', error: error.message });
    }
};

const fetchProjectAddressByRouteId = async (req, res) => {
    try {
        const { selectedRoute } = req.body;
        let projectAddress = await Route.fetchAddressByRouteId(selectedRoute);
        if (projectAddress) {
            return res.send({ status: 1, message: 'Data fetched successfully',projectAddress});
        } else {
            return res.send({ status: 0, message: 'Failed to fetch location' });
        }
    } catch (error) {
      console.error('fetchProjectAddressByRouteId error:', error);
      return res.send({ status: 500, message: 'Server error', error: error.message });
    }
};

const fetchRouteLocationsBySalesId = async (req, res) => {
    try {
        const { selectedRoute } = req.body;
        const routeData = await Route.fetchRouteLocationsBySalesId(selectedRoute);
        console.log('routeData',routeData)
        // const productData = await Route.fetchRouteProductsBySalesId(selectedRoute);
        if (routeData ) {
            return res.send({ status: 1, message: 'Data fetched successfully', routeData:routeData });
        } else {
            return res.send({ status: 0, message: 'Failed to fetch locations and products' });
        }
    } catch (error) {
      console.error('fetchRouteLocationsByRouteId error:', error);
      return res.send({ status: 500, message: 'Server error', error: error.message });
    }
};

const fetchRoutesWithLocations = async (req, res) => {
    try {
        const requestId = req?.body?.requestId || null;
        const routeData = await Route.fetchAllTSRoutes(requestId);
        if (!routeData || routeData.length === 0) {
            return res.send({ status: 0, message: 'No routes found' });
        }
        const updatedRoutes = await Promise.all(
            routeData.map(async (data) => {
                const routeLocationsData = await Route.fetchRouteLocationsByRouteId(data.id);
                const routeProductsData = await Route.fetchRouteProductsByRouteId(data.id);
                // console.log(`Locations for Route ID ${data.id}:`, routeLocationsData);
                data['locations'] = routeLocationsData;
                data['locations_count'] = (routeLocationsData && routeLocationsData?.length > 0) ? routeLocationsData?.length : 0;
                data['products'] = routeProductsData;
                data['products_count'] = (routeProductsData && routeProductsData?.length > 0) ? routeProductsData?.length : 0;
                return data;
            })
        );
        // console.log(`updatedRoutes : `, updatedRoutes);
        return res.send({ status: 1, message: 'Routes and Locations fetched successfully', routeData: updatedRoutes });
    } catch (error) {
      console.error('fetchRoutesWithLocations error:', error);
      return res.send({ status: 500, message: 'Server error', error: error.message });
    }
};

const getAllProductsForWEDRoute = async (request, reply) => {
  try {
    let results = await Product.getAllProducts(false);
    if (results && results?.length > 0){
        results = results?.filter(row => row.inhouse === 1 || row.inhouse === 5)
        reply.send({ status: 1, results, message: "Data fetched successfully" });
    } else {
        reply.send({ status: 0, results: [], message: "Error fetching data" });
    }
  } catch (error) {
    console.log("Server error", error);
    reply.status(500).send("Server error");
  }
};

const getRouteDataBySalesOrderId=async(req,res)=>{
    try {
        const {salesOrderId} = req.body 
        let data = await Route.getRouteDatabySalesOrderId(salesOrderId)
        if(!empty(data)){
            res.send({
                status:1,data
            })
        }else{
            res.send({
                status:0
            })
        }
    } catch (error) {
        console.log(error)
    }
}

module.exports={
    createRoute,
    getAllRoutes,
    getRouteDataById,
    updateRoute,
    deleteRoute,
    getAllUnAssignedRoutes,
    getInstallationsByRoute,
    assignInstallationToDriver,
    addSelectedRoutes,
    updateRouteStatus,
    deleteCompletedRoute,
    findDataByDriverId,
    demoMessage,
    fetchAllUnassignedSalesorderFromAppointments,
    assignTSJobToRoute,
    getAllAssignedRoutes,
    saveTSRouteLocations,
    fetchRouteLocationsByRouteId,
    fetchRoutesWithLocations,
    getAllProductsForWEDRoute,
    getRouteDataBySalesOrderId,
    fetchRouteLocationsBySalesId,
    fetchProjectAddressByRouteId
}