const { empty } = require('../Helpers/Common');
const Project = require('../models/Projects');
const Admin = require('../models/admin');
const moment = require('moment');
const ProjectTask = require('../models/projectTask')
const Request = require('../models/request')
const Product = require('../models/product')
const JobCost = require("../models/jobCost");
const Driver = require("../models/driver");
const RequestPartner = require('../models/requestPartners')
const Installation = require("../models/installation");
const { values } = require('@babel/runtime/regenerator');
const { default: axios } = require('axios');
const { realmId, getNewAccessToken, PRODUCTION, findAccountIdByAcctNum, qbReceptFromEmailAcc, departmentId, getAccountIdByName } = require('../quickbook/quickbook');
const nodemailer = require('nodemailer');
const path = require("path");
const fs = require("fs");
const RequestActivity = require('../models/RequestActivity')
const Client = require("../models/client");
const { convertDesignOrderPdfToPngHelper, convertPdfToPngHelper } = require('./request');
const Onboard = require("../models/onboard");
const OnboardWorkFlowStages = require("../models/onboardWorkFlowStages");
const CustomerOrderProduct = require("../models/customerOrderProduct");
const { SEND_EMAIL } = require('../constants/constant');
const { getAllWorkflow, addStaffToProject } = require('../models/staffmember');
const transporter = nodemailer.createTransport({
    host: 'mail.signwisesolutions.com', 
    port: 465, 
    secure: true, 
    auth: {
      user: 'noreply@signwisesolutions.com', 
      pass: 'signwise@2024', 
    },
  });
const SplitManagementModel = require('../models/SplitManagementModel');
const SplitManagementController = require('./SplitManagementController')
const { filteredSignwiseInstalations } = require('../Helpers/SplitManagementHelper');
const { getProjectAttachmentByIdForConversion } = require('../models/documentRepository');
const { FACILITY_ID } = require('../config/SplitManagementDb');
const { updateMirrorOrderStatusFromOtherInstallations } = require('./SplitManagementController');
let currentDate = moment().unix();
const sanitizeLog = (s) => s.replace(/\u2192/g, '->');
function formatHoursToHHMMSS(hours) {
    const duration = moment.duration(hours, "hours");
    const formattedDuration = moment
      .utc(duration.asMilliseconds())
      .format("HH:mm:ss");
    return formattedDuration;
}

// Status mapping for activity logs
const statusMapping = {
    1: "New",
    2: "In Progress",
    3: "Completed"
};

const getStatusName = (statusCode, isRequestEstimate = 0) => {
    if (statusCode === 1 && isRequestEstimate === 1) {
        return "In Queue";
    }
    return statusMapping[statusCode] || `Status ${statusCode}`;
};

const updatateProjectStatus = async (req, reply) => {
    try {
        let { status, projectId, userId, request_id ,projectCategory} = req.body
        let currentDate = moment().unix();
        let project = {}
        project['status'] = status;
        project['change_order'] = 0;
        console.log('dataaaaaaaaaaaaaaaaa',req.body)
        if(status==3){
            project['complete']=100
            project['completion']=100
        }
        else{
            project['complete']=0
            project['completion']=0
        }
        let projectDetails = await Project.getProjectById(projectId);
        console.log("#############Data for update",project);
  
        let updated = await Project.updateProject(projectId, project);
       
        if (updated) {
        console.log('projectsssssssssssss', projectDetails)
    //     if(projectDetails){
    //       try {
    //         const facilityTypes = (projectDetails?.facility_type || "")
    //           .split(",")
    //           .map(v => v.trim())
    //           .filter(v => v !== "");
    //         const targetFacilityId = facilityTypes.filter(id => id !== String(FACILITY_ID));
    //         const originRequestId = projectDetails?.request_id || null;
    //         const isSplitOrder = projectDetails?.is_split_order || null;
    //         const project_category = projectDetails?.project_category !== 15 ? true : false;
    //         const installStatus = status == 2 ? 6 : 0
    //         if (isSplitOrder && originRequestId && targetFacilityId && project_category) {
    //           const updateSplitMirrorStatus = await updateMirrorOrderStatusFromOtherInstallations(originRequestId, targetFacilityId, installStatus);
    //           console.log('updateSplitMirrorStatus98765', updateSplitMirrorStatus)
    //         }
    //       } catch (error) {
    //         console.log('error updateSplitMirrorStatus98765', error)
    //       }
    //   }
           // Check if this is a split build order (category 15) in a child facility (for_parent_facility = 1)
           if (projectDetails?.project_category == 15 && projectDetails?.for_parent_facility == 1 && projectDetails?.is_split_order) {
            let updateAllTask=await ProjectTask.updateProjectTaskByProjectIdExcludeCompleted( project,projectId);
            console.log('updateAllTaskssssssss', updateAllTask)
            } else {
                let updateAllTask=await ProjectTask.updateProjectTaskByProjectId( project,projectId);
            }
            // Only update subtasks if the project status is NOT "Inprogress" (status 2)
            if (status !== 2) {
                let updateAllSubtask=await ProjectTask.updateProjectSubTaskByProjectId( project,projectId)
            }
            let teamMembers = await Project.getAllTeam(projectId)
            // console.log("Team membersss", teamMembers)
            let notificationMsg = `The status of the job "${projectDetails['name']}" Updated`
            let notificationUrl = "projects/view-project/" + projectId;
            let notificationData = {};

            for (const team of teamMembers) {

                const incrementResult = await Admin.incrementField(userId, "noti_count", 1);
                notificationData = {
                    user_id: team.userid,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: userId,
                };

                const addNotificationResult = await Admin.addNotification(notificationData);


            }
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }
            // const allUserIds = await Admin.getAllUserIds();
            // const allUserIds = await Admin.getAllAdminUserIds();
            // let PartnerUserIds = await RequestPartner.fetchPartnerUserIds(projectDetails?.request_id)
            // const project_members = await Project.getAllMemberUserIdsByProjectId(projectId)
            // console.log("project_memberss 2" , project_members)
            // const usersToUpdate = [...new Set([userId, PartnerUserIds, ...project_members, ...allUserIds].filter(Boolean))];

            // const updateProductionCount = async (userId) => {
            //   await Project.jobTabIncrementField(userId, 'pre_production_count', -1, 'pre_production_count_ids', projectId, false);
            //   await Project.jobTabIncrementField(userId, 'production_count', 1, 'production_count_ids', projectId, true);
            //   console.log("Updated job tab: -1 pre_production, +1 production");
            // };
          
            // await Promise.all(usersToUpdate.map(user => updateProductionCount(user)));

            // Log the status change activity for the request
            if (request_id) {
                let requestData = await Request.getRequestById(request_id);
                const isRequestEstimate = requestData && requestData[0]?.is_request_estimate ? 1 : 0;
                
                const oldStatusName = getStatusName(projectDetails?.status, isRequestEstimate);
                const newStatusName = getStatusName(status, isRequestEstimate);
                let statusChangeMsg = `📋 Job status changed from "${oldStatusName}" to "${newStatusName}"`;
                
                let requestActivity = {
                    request_id: request_id,
                    activity: statusChangeMsg,
                    added_by: userId,
                    timestamp: currentDate,
                    status: 1
                };
                
                try {
                    let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity);
                    console.log('Status change activity logged:', reqActivityId);
                } catch (error) {
                    console.log('Error logging status change activity:', error);
                }
            }

            if(projectCategory ==12){
                const updateRequestTable = await Request.updateRequets(request_id,{isReview :2})
              let requestData = await Request.getRequestById(request_id);
              

                let requestPartners = await RequestPartner.getRequestPartnerByIds({}, request_id)
                let reqActivityMsg = "✅ Job has been completed and sent for review"
                let notificationMsg = `✅ The Sales Order ${requestData[0].name} has been completed and sent for review.`;
                let notificationUrl = `request/view/${request_id}`;

                    const currentDate = moment().unix();  
                    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 notificationData = {};
                    if (requestPartners.length > 0) {
                        for (const reqId of requestPartners) {
                        console.log("$$$$$$$$$$$$$", reqId);
                        const incrementResult = await Admin.incrementField(reqId['id'], "noti_count", 1);

                        notificationData = {
                            user_id: reqId['id'],
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: userId,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);
                        }
                    }

                     let requestActivity = {}
                        requestActivity['request_id'] = request_id;
                        requestActivity['activity'] = reqActivityMsg
                        requestActivity['added_by'] = userId
                        requestActivity['timestamp'] = currentDate
                        requestActivity['status'] = 1
                        let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)

                                
            }

            reply.send({ status: 1, message: "Job status Updated" });
        }
        else {
            reply.send({ status: 0, message: "Failed to update Job status " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }


}
const updatateJobHoldStatus = async (req, reply) => {
    console.log("fetchedddd")
    try {
        let { projectId, userId, reason,request_id } = req.body
        console.log('request_id----',request_id)
        let currentDate = moment().unix();
        let project = {}
        let projectDetails = await Project.getProjectById(projectId);
        const facilityTypes = (projectDetails?.facility_type || "")
              .split(",")
              .map(v => v.trim())
              .filter(v => v !== "");
        const targetFacilityId = facilityTypes?.filter(id => id !== String(FACILITY_ID));
        const originRequestId = projectDetails?.request_id || null;
        const isSplitOrder = projectDetails?.is_split_order || null;
        const project_category = projectDetails?.project_category !== 15 ? true : false;
        if(projectDetails?.hold==0){
            project['hold'] = 1;
            project['change_order'] = 0;
            project['reason'] = reason || projectDetails.reason;    
            project['request_id'] = request_id;
        }else{
            project['hold'] = 0;
            project['change_order'] = 0;
            project['request_id'] = request_id;
        }
        project['timestamp'] = currentDate;
        let updated = await Project.updateProject(projectId, project);
        const reqHoldData = {
            hold: project?.hold,
            hold_reason: project?.reason,
            timestamp: currentDate,
        }
        console.log(reqHoldData,'reqHoldData');
        
        let updateRequest = await Request.updateRequestById(request_id,reqHoldData);

        if(isSplitOrder && originRequestId && targetFacilityId && project_category){
            const jobHoldData = {
                hold: project?.hold,
                reason: project?.reason,
            }
            const updateHoldStatus = await SplitManagementController.updateTargetedFacilityHoldStatusFromOtherInstallations(originRequestId, targetFacilityId, reqHoldData,jobHoldData);
            console.log('updateHoldStatus32312312 project', updateHoldStatus)
          }

        if (updated && updateRequest) {  
            //const allUserIds = await Admin.getAllUserIds();
            // const allUserIds = await Admin.getAllAdminUserIds();
            // const selectedClientId = values?.clients?.user_id ||null;
            // let PartnerUserIds = await RequestPartner.fetchPartnerUserIds(projectDetails?.request_id)
            // const projectResult = await Project.getProjectByRequestId(projectDetails?.request_id);
            // const project_members = await Project.getAllMemberUserIdsByProjectId(projectResult)
            // const moveProjectToHoldTab = async (userId, projectId) => {
            //     console.log("inside of move")
            //     projectId = projectId.toString();
            //     const record = await Project.getJobsTabCountByUser(userId);
            //     console.log("record")
            //     if (!record) return;
              
            //     const tabFields = [
            //       'pre_production',
            //       'production',
            //       'installs',
            //       'pickup',
            //       'shipping',
            //       'completed'
            //     ];
            //     console.log("fetched 2")
              
            //     for (let field of tabFields) {
            //         console.log("fetched 3")
            //       const fieldIds = `${field}_count_ids`;
            //       const countField = `${field}_count`;
            //   console.log("fetched 4")
            //   const rawIds = record[fieldIds] || '';
            //   const ids = rawIds.split(',').map(id => id.trim());
            //   if (ids.includes(projectId.toString())) {
            //         console.log("fetched 5")
            //         await Project.jobTabIncrementField(userId, countField, -1, fieldIds, projectId, false);
            //         console.log(`Jobs tab: Removed project ${projectId} from ${field} tab for user ${userId}`);
 
            //         await Project.jobTabIncrementField(userId, 'hold_count', 1, 'hold_count_ids', projectId, true);
            //         console.log(`Jobs tab: Added project ${projectId} to hold tab for user ${userId}`);
              
            //         break; 
            //       }
            //     }
            //   }; 
            //   if (project?.hold === 1) {
            //     console.log("fetched hold")
            //     const allUsersToUpdate = [...new Set([userId, ...PartnerUserIds,...allUserIds].filter(Boolean))];
            //     await Promise.all(allUsersToUpdate.map(user => moveProjectToHoldTab(user, projectId)));
            //   }
            //   else if (project?.hold === 0) {
            //     const allUsersToUpdate = [...new Set([userId, ...PartnerUserIds, ...allUserIds].filter(Boolean))];
              
            //     const removeFromHoldTab = async (userId, projectId) => {
            //         projectId = projectId.toString();
            //       const record = await Project.getJobsTabCountByUser(userId);
            //       if (!record) return;
              
            //       const fieldIds = `hold_count_ids`;
            //       const countField = `hold_count`;
              
            //     const rawIds = record[fieldIds] || '';
            //     const ids = rawIds.split(',').map(id => id.trim());
            //     if (ids.includes(projectId.toString())) {
            //         await Project.jobTabIncrementField(userId, countField, -1, fieldIds, projectId, false);
            //         console.log(`Jobs tab: Removed project ${projectId} from hold tab for user ${userId}`);
            //       }
            //     };
              
            //     await Promise.all(allUsersToUpdate.map(user => removeFromHoldTab(user, projectId)));
            //   }       
            // let updateAllTask=await ProjectTask.updateProjectTaskByProjectId( project,projectId);
            // let updateAllSubtask=await ProjectTask.updateProjectSubTaskByProjectId( project,projectId)
            let teamMembers = await Project.getAllTeam(projectId)
            let notificationMsg = ""
            if(project?.hold==1){
            notificationMsg = `The job "${projectDetails['name']}" has been moved to Hold`
            let requestActivity = {}
            requestActivity['request_id'] = request_id;
            requestActivity['activity'] = notificationMsg;
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            } else{
            notificationMsg = `The job "${projectDetails['name']}" has been removed from Hold`
            let requestActivity = {}
            requestActivity['request_id'] = request_id;
            requestActivity['activity'] = notificationMsg;
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            }
            let notificationUrl = "projects/view-project/" + projectId;
            let notificationData = {};

            for (const team of teamMembers) {
                const incrementResult = await Admin.incrementField(userId, "noti_count", 1);
                notificationData = {
                    user_id: team.userid || userId,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: userId,
                };
                const addNotificationResult = await Admin.addNotification(notificationData);
            }
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            for (const adminId of adminIds) {
                if (adminId != userId) {
                    const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);
                    notificationData = {
                        user_id: adminId || userId,
                        url: notificationUrl,
                        timestamp: currentDate,
                        message: notificationMsg,
                        status: 1,
                        from_id: userId,
                    };
                    const addNotificationResult = await Admin.addNotification(notificationData);

                }
            }
            
            reply.send({ status: 1, message: notificationMsg,reqHoldData:reqHoldData });
        }
        else {
            reply.send({ status: 0, message: "Failed to update job status " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }


}
const addProjectTask = async (req, reply) => {
    try {
        let { request_id } = req.body;
        let currentDate = Math.round(moment().valueOf() / 1000);
        let projectTask = {}
        projectTask['name'] = req.body.name;
        projectTask['project_id'] = req.body.projectId;
        projectTask['timestamp'] = currentDate;
        projectTask['userid'] = req.body.userId;
        projectTask['status'] = 1;
        projectTask['task_uid'] = await ProjectTask.getTaskUid(req.body.projectId);
        projectTask['project_task_uid'] = req.body.project_task_uid;
        projectTask['start_date'] = req.body.start ? req.body.start : null
        projectTask['due_date'] = req.body.end ? req.body.end : null
        projectTask['description'] = req.body.description ? req.body.description : null
        projectTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectTask['priority'] = req.body.priority ? req.body.priority : null
        projectTask['cover_image'] = req.body.cover_image ? req.body.cover_image : 'null'
        projectTask['complete'] = 0
        projectTask['is_manually_added'] = 1
        projectTask['complete_sync'] = 1
        projectTask['from_product']=0

        //cover image upload
        let userId = req.body.userId
        const projectTaskId = await ProjectTask.addProjectTask(projectTask);

        if (projectTaskId) {
            let projectTask = await ProjectTask.getProjectTaskById(projectTaskId);
            let allSubtask=await ProjectTask.getAllProjectTasks(req.body.projectId,userType=1)
            let  firstTaskStatus=allSubtask[0].status
          const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
          const averageCompletionTask = sumCompletionTask / allSubtask.length;
          const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
          let projectTaskData = {};
          projectTaskData.completion=averageCompletionTask
          
          if(tasksWithStatusCompletedTasks){
            projectTaskData.status=firstTaskStatus
         }
         else{
           projectTaskData.status=1
         }

          console.log("###############AllSubTask",projectTaskData);
          let resultStatus = await Project.updateProject(req.body.projectId,projectTaskData);
          console.log("###############AllSubTask",resultStatus);

            const formattedString = projectTask['short_code'] + String(projectTask['task_uid']).padStart(4, '0');
            let notificationMsg = "New job task has been added."
            let notificationUrl = "projects/view-project/" + req.body.projectId
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            let notificationData_user = {
                user_id: userId,
                url: notificationUrl,
                timestamp: currentDate,
                message: notificationMsg,
                status: 1,
                from_id: userId,
            };
            let requestActivity = {}
            requestActivity['request_id'] = request_id;
            requestActivity['activity'] = notificationMsg;
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            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);
                }
            }
            reply.send({ status: 1, message: "New job task has been added" });
        }
        else {
            reply.send({ status: 0, message: "Failed to add new job task " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }

}
const updateProjectTask = async (req, reply) => {
    try {
        let currentDate = Math.round(moment().valueOf() / 1000);
        let projectTask = {}
        let taskId = req.body.id;
        projectTask['name'] = req.body.name;
        projectTask['start_date'] = req.body.start ? req.body.start : null
        projectTask['due_date'] = req.body.end ? req.body.end : null
        projectTask['description'] = req.body.description ? req.body.description : null
        projectTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectTask['priority'] = req.body.priority ? req.body.priority : null
        projectTask['cover_image'] = 'null'
        projectTask['complete'] = 0
        //cover image upload
        let userId = req.body.userId
        const updated = await ProjectTask.updateProjectTask(projectTask, taskId);
        if (updated) {


            let notificationMsg = "Project task has been updated."
            let notificationUrl = "projects/view-project-task/" + taskId
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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);

                }
            }
            reply.send({ status: 1, message: "Job task has been updated" });
        }
        else {
            reply.send({ status: 0, message: "Failed to update job task " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }

}

const updateTaskWorkflowByOrderProduct = async (req, reply) => {
    try {
        const { customerOrderProductId, requestServiceId, workflowId } = req.body;

        if (!workflowId || (!customerOrderProductId && !requestServiceId)) {
            return reply.send({
                status: 0,
                message: "workflowId is required and either customerOrderProductId (product task) or requestServiceId (service task) must be provided"
            });
        }

        const workflow = await Onboard.getWorkFlowbyId(Number(workflowId));
        if (!workflow || workflow.length === 0) {
            return reply.send({ status: 0, message: "Invalid workflow selected" });
        }

        const targetWorkflowId = Number(workflowId);
        const updated = customerOrderProductId
            ? await CustomerOrderProduct.updateCustomerOrderProduct(
                { workflow: targetWorkflowId },
                Number(customerOrderProductId)
            )
            : await Request.updateRequestServiceWorkflowById(Number(requestServiceId), targetWorkflowId);

        if (updated) {
            // Rebuild subtasks from selected workflow stages for all mapped project tasks.
            const workflowStages = await OnboardWorkFlowStages.getStagesDataByWorkflowId(Number(workflowId));
            const taskIds = customerOrderProductId
                ? await ProjectTask.getTaskIdsByCustomerOrderProductId(Number(customerOrderProductId))
                : await ProjectTask.getTaskIdsByRequestServiceId(Number(requestServiceId));

            // Determine affected project_id (all mapped tasks should belong to same project)
            let affectedProjectId = null;
            if (taskIds?.length) {
                const firstTaskDetails = await ProjectTask.getProjectTaskBytaskId(taskIds[0]);
                const firstTaskInfo = firstTaskDetails?.[0] || {};
                affectedProjectId = firstTaskInfo?.project_id || null;
            }

            for (const mappedTaskId of taskIds) {
                const existingSubTasks = await ProjectTask.fetchSubTasksByTaskId(mappedTaskId);
                for (const subTask of existingSubTasks) {
                    const subTaskId = subTask?.id || subTask?.ID;
                    if (!subTaskId) continue;
                    await ProjectTask.deleteProjectMembersBySubtaskId(subTaskId);
                    await ProjectTask.deleteProjectSubTask(subTaskId);
                }

                if (!workflowStages || workflowStages.length === 0) {
                    continue;
                }

                const taskDetails = await ProjectTask.getProjectTaskBytaskId(mappedTaskId);
                const taskInfo = taskDetails?.[0] || {};
                const taskUid = await ProjectTask.getSubTaskUid(mappedTaskId);
                const now = moment().unix();

                for (const stage of workflowStages) {
                    const rawSkillIds = Array.isArray(stage?.skill_ids)
                        ? stage.skill_ids.join(',')
                        : (stage?.skill_ids ?? null);
                    // Normalize to "1,2,3" (service workflows sometimes store skill_ids in different string formats)
                    const stageSkillIds = rawSkillIds
                        ? (String(rawSkillIds).match(/\d+/g)?.join(',') || null)
                        : null;

                    const subTaskPayload = {
                        name: stage?.name || "Stage",
                        task_id: mappedTaskId,
                        timestamp: now,
                        userid: taskInfo?.userid || req.body?.userId || 1,
                        start_date: taskInfo?.start_date || null,
                        due_date: taskInfo?.due_date || null,
                        task_uid: taskUid,
                        complete: 0,
                        complete_sync: 1,
                        status: 1,
                        skill_ids: stageSkillIds,
                        reporter_id: taskInfo?.reporter_id || 1,
                        priority: taskInfo?.priority || 1,
                        description: stage?.exit_message || stage?.message || null
                    };

                    const projectSubTaskId = await ProjectTask.addProjectSubTask(subTaskPayload);

                    // Assign members to each regenerated subtask based on stage skills
                    if (projectSubTaskId && stageSkillIds) {
                        const projectManagers = await Project.getTeamMembersBasedOnSkills(stageSkillIds, 14);
                        if (projectManagers?.length > 0) {
                            for (const projectManager of projectManagers) {
                                const memberToSubTask = {
                                    subtask_id: projectSubTaskId,
                                    staff_id: projectManager?.id || null
                                };
                                if (memberToSubTask.staff_id) {
                                    await ProjectTask.AddMembersToSubTask(memberToSubTask);
                                }
                            }
                        }
                    }
                }
            }

            // Sync job members (project_members) after workflow change:
            // - add anyone assigned to any subtask in the job
            // - remove ONLY workflow-skill-based members if they aren't assigned to any subtask
            // - never remove collaborators/clients/protected roles
            if (affectedProjectId) {
                await Project.syncSkillBasedProjectMembersBySubtasks(affectedProjectId, {
                    protectedUserTypes: [1], // superadmin
                });
            }

            return reply.send({ status: 1, message: "Workflow updated successfully" });
        }

        return reply.send({ status: 0, message: "Failed to update workflow" });
    } catch (error) {
        console.log("updateTaskWorkflowByOrderProduct error:", error);
        return reply.status(500).send({ status: 0, message: "Server error:" + error });
    }
}
const updatateProjectTaskStatus = async (req, reply) => {
    try {
        let { status, taskId, userId,projectId,projectCategory,request_id } = req.body
        let currentDate = moment().unix();
        let projectTask = {}
        projectTask['status'] = status;
        let projectTaskDetails = await ProjectTask.getProjectTaskBytaskId(taskId)
        const updated = await ProjectTask.updateProjectTask(projectTask, taskId);
        
        // Update subtasks status with the same task ID
        const subtaskUpdateData = { status: status };
        await ProjectTask.updateProjectSubTaskByTaskId(subtaskUpdateData, taskId);
        
        if (updated) {
            let allProjectTaskDetails = await ProjectTask.getTasksByProjectId(projectId)
            console.log("allProjectTaskDetails",allProjectTaskDetails)
            const allProjectCompleted = allProjectTaskDetails.every(task => task.status === 3)

            if(allProjectCompleted){
                let data ={
                 status:3
                }
              await  Project.updateProjectById(projectId,data)
            }
        

            let notificationMsg = `The status of the job "${projectTaskDetails[0]['name']}" Task has been Updated`
            let notificationUrl = "projects/view-project-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }

               if(projectCategory ==12){
                const updateRequestTable = await Request.updateRequets(request_id,{isReview :2})
              let requestData = await Request.getRequestById(request_id);
              

                let requestPartners = await RequestPartner.getRequestPartnerByIds({}, request_id)
                let reqActivityMsg = "✅ Job has been completed and sent for review"
                let notificationMsg = `✅ The Sales Order ${requestData[0].name} has been completed and sent for review.`;
                let notificationUrl = `request/view/${request_id}`;

                    const currentDate = moment().unix();  
                    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 notificationData = {};
                    if (requestPartners.length > 0) {
                        for (const reqId of requestPartners) {
                        console.log("$$$$$$$$$$$$$", reqId);
                        const incrementResult = await Admin.incrementField(reqId['id'], "noti_count", 1);

                        notificationData = {
                            user_id: reqId['id'],
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: userId,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);
                        }
                    }

                     let requestActivity = {}
                        requestActivity['request_id'] = request_id;
                        requestActivity['activity'] = reqActivityMsg
                        requestActivity['added_by'] = userId
                        requestActivity['timestamp'] = currentDate
                        requestActivity['status'] = 1
                        let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)

                                
            }


            reply.send({ status: 1, message: "Project Task status  has been Updated",allProjectCompleted });
        }
        else {
            reply.send({ status: 0, message: "Failed to update Project task status " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }


}

const checkAllProjectTasksCompletedStatus = async (req, reply) => {
    try {
        const { projectId, userId } = req.body;

        if (!projectId || !userId) {
            return reply.status(400).send({ status: 0, message: "projectId and userId are required" });
        }

        const allTasks = await ProjectTask.getAllProjectTasks(projectId, userId, 1);
        const pendingTasks = allTasks.filter(task => task.status !== 3);

        let allProjectCompleted = false;


        if (pendingTasks.length === 1) {
            allProjectCompleted = true;
        }

        return reply.send({ status: 1, allProjectCompleted, pendingTasks });

    } catch (error) {
        return reply.status(500).send({ status: 0, message: "Server error: " + error.message });
    }
};


const addProjectSubTask = async (req, reply) => {
    try {
        let currentDate = Math.round(moment().valueOf() / 1000);
        let { request_id } = req.body;
        let projectId=req.body.projectId
        console.log(req.body,'-----------------req.body')
        let projectSubTask = {}
        projectSubTask['name'] = req.body.name;
        projectSubTask['task_id'] = req.body.taskId;
        projectSubTask['timestamp'] = currentDate;
        projectSubTask['userid'] = req.body.userId;
        projectSubTask['status'] = 1;       
        projectSubTask['skill_ids'] = req.body.skills?.map((item)=>item.id).join(',')      
        projectSubTask['task_uid'] = await ProjectTask.getSubTaskUid(req.body.taskId);
        // projectTask['project_task_uid'] = req.body.project_task_uid;
        projectSubTask['start_date'] = req.body.start ? req.body.start : null
        projectSubTask['due_date'] = req.body.end ? req.body.end : null
        projectSubTask['description'] = req.body.description ? req.body.description : null
        projectSubTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectSubTask['priority'] = req.body.priority ? req.body.priority : null
        projectSubTask['complete'] = 0
        projectSubTask['complete_sync'] = 1

       
        //cover image upload
        let userId = req.body.userId
        const projectSubTaskId = await ProjectTask.addProjectSubTask(projectSubTask);
       
        if (projectSubTaskId) {
            let memberToSubTask={}
            let members=req.body?.assignedTo.split(",").map(value => value.trim());
            for(let i=0;i<members.length;i++){
                console.log("##########Members",members[i]);
                memberToSubTask['subtask_id'] = projectSubTaskId
                memberToSubTask['staff_id'] = members[i]
                const resAddMemberToSubTask = await ProjectTask.AddMembersToSubTask(memberToSubTask)
                
                // Add staff member to project using the new model (only for time and material or project_categories.id == 12)
                console.log("daddadadadad",members[i])
                if (req.body.isTimeAndMaterial || req.body.projectCategoryId == 12) {
                    console.log("daddadadadad",members[i])
                    const data={
                        staff_id:members[i],
                        sub_task_id:projectSubTaskId
                    }
                    const addToProjectResult = await addStaffToProject(data, projectId);
                    if (addToProjectResult.status === 1) {
                        console.log(`Staff member ${members[i]} added to project ${projectId}`);
                    } else if (addToProjectResult.status === 0 && addToProjectResult.message.includes('already exists')) {
                        console.log(`Staff member ${members[i]} already exists in project ${projectId}`);
                    } else {
                        console.log(`Failed to add staff member ${members[i]} to project ${projectId}:`, addToProjectResult.message);
                    }
                }
            }
           
            
            let projectTask = await ProjectTask.getProjectSubTaskById(projectSubTaskId);
            let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                req.body.taskId,userType=1,
              );
              const tasksWithStatusCompleted = projectSubTask.every(task => task.status === 3);
              const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
              const averageCompletion = sumCompletion / projectSubTask.length;
              const subTasksComplete = projectSubTask.filter(task => task.status === 3);
              let completion=0
              if(!empty(subTasksComplete)){
                let data=100/projectSubTask.length
                completion=data*subTasksComplete.length
              }
             else{
                completion=0
             }
              let project = {};
              project.complete=completion
              if(tasksWithStatusCompleted){
                project.status=3
             }
             else{
               project.status=1
             }

              let result = await ProjectTask.updateProjectTask(project,req.body.taskId);
              let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
             const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
             const averageCompletionTask = sumCompletionTask / allSubtask.length;
             const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === 3);
            let projectTaskData = {};
            projectTaskData.completion=averageCompletionTask
            if(tasksWithStatusCompletedTasks){
                projectTaskData.status=3
             }
             else{
               projectTaskData.status=1
             }

           let resultStatus = await Project.updateProject(projectId,projectTaskData);

            const formattedString = projectTask['short_code'] + String(projectTask['task_uid']).padStart(4, '0');
            let notificationMsg = "New job sub task has been added."
            let notificationUrl = "projects/view-project-task/" + req.body.taskId
            let requestActivity = {}
            requestActivity['request_id'] = request_id;
            requestActivity['activity'] = notificationMsg;
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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);

                }
            }
            reply.send({ status: 1, message: "New job sub task has been added" });
        }
        else {
            reply.send({ status: 0, message: "Failed to add new job sub task " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }
}
const viewSubTask = async (req, reply) => {
    let { id } = req.body
    let projectSubTask = await ProjectTask.getProjectSubTaskById(id);
    // let projectMembers = await Project.getAllProjectMembers(projectId)
    if (projectSubTask) {
        reply.send({
            status: 1,
            result: projectSubTask,
            // projectMembers,
            msg: "Project sub task fetched successfully"
        });
    }
    else {
        reply.send({ 'status': 0, msg: "Failed to fetch job sub task", });
    }
}
const updateProjectSubTask = async (req, reply) => {
    try {
        let currentDate = Math.round(moment().valueOf() / 1000);
        let projectId = req.body.projectId
        let projectTask = {}
        let taskId = req.body.id;
        projectTask['name'] = req.body.name;
        projectTask['start_date'] = req.body.start ? req.body.start : null
        projectTask['due_date'] = req.body.end ? req.body.end : null
        projectTask['skill_ids'] = req.body.skills?.map((item)=>item.id).join(',')  
        projectTask['description'] = req.body.description ? req.body.description : null
        projectTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectTask['priority'] = req.body.priority ? req.body.priority : null
        projectTask['complete'] = 0
        projectTask['complete_sync'] = 1
        //cover image upload
        let userId = req.body.userId
        let deleted=await ProjectTask.deleteProjectMembersBySubtaskId(taskId)
        let deletedForUpdate=await Project.deleteProjectMembersBySubtaskIdForUpdate(taskId)
        let addedForUpdate=await Project.addProjectMember(taskId)
            let memberToSubTask={}
            let members=req.body?.assignedTo.split(",").map(value => value.trim());
            for(let i=0;i<members.length;i++){
                console.log("##########Members",members[i]);
                memberToSubTask['subtask_id'] = taskId,
                memberToSubTask['staff_id'] = members[i]
                const resAddMemberToSubTask = await ProjectTask.AddMembersToSubTask(memberToSubTask)
            }
        const updated = await ProjectTask.updateProjectSubTask(projectTask, taskId);

        // Automatically start stopwatch if status is 'in progress' (status: 1)
        if (req.body.status === 1) {
            const startTime = Math.round(moment().valueOf() / 1000);
            const stopwatchData = {
                user_id: userId,
                job_id: projectId,
                subtask_id: taskId,
                start_time: startTime,
                status: 1 // 1 for running
            };
            await ProjectTask.addStopwatch(stopwatchData);
        }

        if (updated||deleted) {
            let deleted=await ProjectTask.deleteProjectMembersBySubtaskId(taskId)
            let memberToSubTask={}
            let members=req.body?.assignedTo.split(",").map(value => value.trim());
            for(let i=0;i<members.length;i++){
                console.log("##########Members",members[i]);
                memberToSubTask['subtask_id'] = taskId
                memberToSubTask['staff_id'] = members[i]
                const resAddMemberToSubTask = await ProjectTask.AddMembersToSubTask(memberToSubTask)
                if(req.body.isTimeAndMaterial || req.body.projectCategoryId == 12){
                const data={
                    staff_id:members[i],
                    sub_task_id:taskId
                }
                const addToProjectResult = await addStaffToProject(data, projectId);
                }
            }

            let notificationMsg = "Project sub task has been updated."
            let notificationUrl = "projects/view-project-sub-task/" + taskId
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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);

                }
            }
            reply.send({ status: 1, message: "job sub task has been updated" });
        }
        else {
            reply.send({ status: 1, message: "job sub task has been updated " });
        }
    }
    catch (error) {
        console.log("Error**********"+error);
        reply.status(500).send({ message: "Server error:" + error })
    }

}
const deleteProjectTaskMember = async (req, reply) => {
    let currentDate=moment().unix();
    let projectId = req.body.projectId
    let memberId = req.body.id
    let project = await Project.getProjectById(projectId);
    let projectMembers = await ProjectTask.getProjectMemberById(memberId)
    let deleted = await Project.deleteProjectMember(memberId);
    if (deleted) {
        // // Notification
        let notificationMsg = `The job Member  "${projectMembers[0].name}" has been deleted.`;
        let notificationUrl = "projects/view-project-task/";

        let adminIds = await Admin.getAllAdminIds();
        let notificationData = {};

        for (const adminId of adminIds) {

            const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

            notificationData = {
                user_id: adminId,
                url: notificationUrl,
                timestamp: currentDate,
                message: notificationMsg,
                status: 1,
                from_id:project.added_by,
            };

            const addNotificationResult = await Admin.addNotification(notificationData);

        }
        reply.send({ status: 1, message: `The job Member "${projectMembers[0].name}" has been deleted successfully!` })
    }
    else {
        reply.send({ status: 0, message: `Unable to delete the job Member!` })
    }
}
const deleteProjectTask = async (request, reply) => {
    try {
        let { id, status } = request.body;
        let projectId=request.body.projectId
        let currentDate = Math.round(moment().valueOf() / 1000);
        if (!empty(id)) {
           
            let project = await ProjectTask.getProjectTaskBytaskId(id)
           
            if (status == 2) {
                let deleted = await ProjectTask.deleteProjectTask(id);


                if (deleted) {
                    // // Notification
                    // let projectTask = await ProjectTask.getProjectTaskById(projectTaskId);
                    let allSubtask=await ProjectTask.getAllProjectTasks(req.body.projectId,userType=1)
                    let  firstTaskStatus=allSubtask[0].status
                  const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                  const averageCompletionTask = sumCompletionTask / allSubtask.length;
                  const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                  let projectTaskData = {};
                  projectTaskData.completion=averageCompletionTask||0
                  if(!empty(allSubtask)){
                  if(tasksWithStatusCompletedTasks){
                    projectTaskData.status=firstTaskStatus
                 }
                 else{
                   projectTaskData.status=1
                 }
                }
                else{
                    projectTaskData.status=1 
                }
                  console.log("###############AllSubTask",projectTaskData);
                  let resultStatus = await Project.updateProject(req.body.projectId,projectTaskData);
                  console.log("###############AllSubTask",resultStatus);
                    let notificationMsg = `The job   "${project[0].name}" has been deleted.`;
                    let notificationUrl = "projects/view-project-task/";
                 
                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};
                  
                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 1, message: `The job  "${project[0].name}" has been deleted successfully!` })
                }
                else {
                    reply.send({ status: 0, message: `Unable to delete the job!` })
                }
            }
            else if (status == 1) {

                let deleted = await ProjectTask.updateProjectTask(id, { status: status })

                if (deleted) {
                    // // Notification
                    let notificationMsg = `The job task "${project[0].name}" has been deactivated.`;
                    let notificationUrl = "job";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 2, message: `The job task "${project[0].name}" has been made to active!` })
                }
                else {
                    reply.send({ status: 3, message: "Unable to activate the job task!" })
                }
            }
            else if (status === 0) {
                let deleted = await ProjectTask.updateProjectTask({ status: status },id);

                if (deleted) {
                   
                    let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                    let projectTaskData = {};
                    
                  if(!empty(allSubtask)){
                    let  firstTaskStatus=allSubtask[0].status
                    console.log("###############Firsttask",allSubtask);
                  const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                  const averageCompletionTask = sumCompletionTask / allSubtask.length;
                  const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                  
                  projectTaskData.completion=averageCompletionTask||0
                    console.log("###############Firsttask",tasksWithStatusCompletedTasks);
                  if(tasksWithStatusCompletedTasks){
                    projectTaskData.status=firstTaskStatus
                 }
                 else{
                   projectTaskData.status=1
                 }
                }
                else{
                    projectTaskData.status=1 
                }
                    // Notification
                    console.log("#############projecttask",projectTaskData);
                    let resultStatus = await Project.updateProject(request.body.projectId,projectTaskData);
                    let notificationMsg = `The job task"${project[0].name}" has been deactivated.`;
                    let notificationUrl = "job";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id:project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }

                    reply.send({ status: 4, message: `The job"${project[0].name}" has been deleted!` })
                }
                else {
                    reply.send({ status: 5, message: "Unable to deactivate the job!" })
                }
            }
        }
        else {
            console.log("Error................")
            reply.send({ status: 500, message: "Error!" })
        }
    }
    catch (error) {
        console.log("#################errOR",error);
        reply.status(500).send({ message: "Server error"+error })
    }
}
const deleteProjectSubTask = async (request, reply) => {
    try {
        let { id, status,taskId,projectId,isTimeAndMaterial, projectCategoryId} = request.body;
        let currentDate = Math.round(moment().valueOf() / 1000);
        if (!empty(id)) {
            let project = await ProjectTask.getProjectSubTaskById(id)

            if (status == 2) {
                let deleted = await ProjectTask.deleteProjectSubTask(id);
                

                if (deleted) {
                    // // Notification
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                      if(isTimeAndMaterial){
                        let deletedForUpdate=await Project.deleteProjectMembersBySubtaskIdForUpdate(id)
                    }
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      let project = {};
                      project.complete=averageCompletion
                      let result = await ProjectTask.updateProjectTask(project,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const firstTaskStatus = allSubtask[0]?.status;
                      console.log("TaskStatus----------------",firstTaskStatus);
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=firstTaskStatus
                     }
                     else{
                       projectTask.status=1
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    let notificationMsg = `The job subtask "${project[0].name}" has been deleted.`;
                    let notificationUrl = "projects/view-project-task/";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 1, message: `The job subtask "${project[0].name}" has been deleted successfully!` })
                }
                else {
                    reply.send({ status: 0, message: `Unable to delete the job subtask!` })
                }
            }
            else if (status == 1) {

                let deleted = await ProjectTask.updateProjectSubTask(id, { status: status })

                if (deleted) {
                    // // Notification
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      let project = {};
                      project.complete=averageCompletion
                      if(isTimeAndMaterial){
                        let deletedForUpdate=await Project.deleteProjectMembersBySubtaskIdForUpdate(id)
                    }
                      let result = await ProjectTask.updateProjectTask(project,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === 3);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=3
                     }
                     else{
                       projectTask.status=1
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    let notificationMsg = `The job subtask "${project[0].name}" has been deactivated.`;
                    let notificationUrl = "jobs";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 2, message: `The job subtask "${project[0].name}" has been activated!` })
                }
                else {
                    reply.send({ status: 3, message: "Unable to activate the job subtask!" })
                }
            }
            else if (status == 0) {
                let deleted = await ProjectTask.updateProjectSubTask({ status: status }, id);
                if(isTimeAndMaterial || projectCategoryId == 12){
                let deletedForUpdate=await Project.deleteProjectMembersBySubtaskIdForUpdate(id)
                }
                if (deleted) {
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      console.log("###########sumCompletion",projectSubTask); 
                      console.log("###########averageCompletion",averageCompletion); 
                      const firstSubTaskStatus = projectSubTask[0]?.status;
                    
                      const subTasksComplete = projectSubTask.filter(task => task.status === 3);
                      const subTasksNew = projectSubTask.filter(task => task.status === 1);
                      let completion=0
                                  if(!empty(subTasksComplete)){
                                    let data=100/projectSubTask.length
                                    completion=data*subTasksComplete.length
                                  }
                                 else{
                                    completion=0
                                 }  
                      const tasksWithStatusCompleted = projectSubTask.every(task => task.status === firstSubTaskStatus);
                    
                      let projectData = {};
                      projectData.complete=completion
                      if(!empty(projectSubTask)){
                        if(tasksWithStatusCompleted){
                            projectData.status=firstSubTaskStatus
                         }
                         else{
                            projectData.status=subTasksNew?.length>0?1:2
                         }
                      }
                      else{
                        projectData.status=1
                      }
                     
                     console.log("###########projectData",projectData); 
                      let result = await ProjectTask.updateProjectTask(projectData,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const firstTaskStatus = allSubtask[0]?.status;
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                      const tasksNew = allSubtask.filter(task => task.status === 1);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=firstTaskStatus
                     }
                     else{
                       projectTask.status=tasksNew?.length>0?1:2
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    // Notification
                    let notificationMsg = `The job subtask"${project[0].name}" has been deactivated.`;
                    let notificationUrl = "jobs";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }

                    reply.send({ status: 4, message: `The job subtask "${project[0].name}" has been deleted!` })
                }
                else {
                    reply.send({ status: 5, message: "Unable to delete the job subtask!" })
                }
            }
        }
        else {
            console.log("Error................")
            reply.send({ status: 500, message: "Error!" })
        }
    }
    catch (error) {
        console.log("Error................",error)
        reply.status(500).send({ message: "Server error"+error })
    }
}
const deleteDesignOrderProjectTaskMember = async (req, reply) => {
    let currentDate=moment().unix();
    let designOrderId = req.body.projectId
    let memberId = req.body.id
    let userId = req.body.userId || req.body.added_by

    let project = await Project.getDesignOrderProjectById(designOrderId);
    let projectMembers = await Request.getAllDesignOrderProjectMembers(designOrderId,memberId);
    console.log('projectMembers==',projectMembers)
    let deleted = await Request.deleteDesignOrdersProjectMemberById(memberId);
    if (deleted) {
        // Add update entry for Job Log
        if (projectMembers && projectMembers.length > 0 && projectMembers[0].name && userId) {
            const userData = await Admin.getUserById(userId);
            const userName = userData && userData[0] ? `${userData[0].first_name} ${userData[0].last_name}` : 'Unknown User';
            const memberName = projectMembers[0].name;
            const activityMsg = `<strong>${userName}</strong> removed member <strong>${memberName}</strong> from the design order "<strong>${project.name}</strong>".`;
            
            let requestActivity = {
                design_order_id: designOrderId,
                activity: activityMsg,
                added_by: userId,
                timestamp: currentDate
            };
            await RequestActivity.addDesignOrderUpdate(requestActivity);
        }
        
        // // Notification
        let notificationMsg = `The job Member  "${projectMembers[0].name}" has been deleted.`;
        let notificationUrl = "design-order-job/view-task/";

        let adminIds = await Admin.getAllAdminIds();
        let notificationData = {};

        for (const adminId of adminIds) {

            const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

            notificationData = {
                user_id: adminId,
                url: notificationUrl,
                timestamp: currentDate,
                message: notificationMsg,
                status: 1,
                from_id:project.added_by,
            };

            const addNotificationResult = await Admin.addNotification(notificationData);

        }
        reply.send({ status: 1, message: `The job Member "${projectMembers[0].name}" has been deleted successfully!` })
    }
    else {
        reply.send({ status: 0, message: `Unable to delete the job Member!` })
    }
}
const deleteDesignOrderProjectTask = async (request, reply) => {
    try {
        let { id, status } = request.body;
        let projectId=request.body.projectId
        let currentDate = Math.round(moment().valueOf() / 1000);
        if (!empty(id)) {
           
            let project = await ProjectTask.getProjectTaskBytaskId(id)
           
            if (status == 2) {
                let deleted = await ProjectTask.deleteProjectTask(id);


                if (deleted) {
                    // // Notification
                    // let projectTask = await ProjectTask.getProjectTaskById(projectTaskId);
                    let allSubtask=await ProjectTask.getAllProjectTasks(req.body.projectId,userType=1)
                    let  firstTaskStatus=allSubtask[0].status
                  const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                  const averageCompletionTask = sumCompletionTask / allSubtask.length;
                  const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                  let projectTaskData = {};
                  projectTaskData.completion=averageCompletionTask||0
                  if(!empty(allSubtask)){
                  if(tasksWithStatusCompletedTasks){
                    projectTaskData.status=firstTaskStatus
                 }
                 else{
                   projectTaskData.status=1
                 }
                }
                else{
                    projectTaskData.status=1 
                }
                  console.log("###############AllSubTask",projectTaskData);
                  let resultStatus = await Project.updateProject(req.body.projectId,projectTaskData);
                  console.log("###############AllSubTask",resultStatus);
                    let notificationMsg = `The job   "${project[0].name}" has been deleted.`;
                    let notificationUrl = "projects/view-project-task/";
                 
                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};
                  
                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 1, message: `The job  "${project[0].name}" has been deleted successfully!` })
                }
                else {
                    reply.send({ status: 0, message: `Unable to delete the job!` })
                }
            }
            else if (status == 1) {

                let deleted = await ProjectTask.updateProjectTask(id, { status: status })

                if (deleted) {
                    // // Notification
                    let notificationMsg = `The job task "${project[0].name}" has been deactivated.`;
                    let notificationUrl = "job";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 2, message: `The job task "${project[0].name}" has been made to active!` })
                }
                else {
                    reply.send({ status: 3, message: "Unable to activate the job task!" })
                }
            }
            else if (status === 0) {
                let deleted = await ProjectTask.updateProjectTask({ status: status },id);

                if (deleted) {
                   
                    let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                    let projectTaskData = {};
                    
                  if(!empty(allSubtask)){
                    let  firstTaskStatus=allSubtask[0].status
                    console.log("###############Firsttask",allSubtask);
                  const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                  const averageCompletionTask = sumCompletionTask / allSubtask.length;
                  const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                  
                  projectTaskData.completion=averageCompletionTask||0
                    console.log("###############Firsttask",tasksWithStatusCompletedTasks);
                  if(tasksWithStatusCompletedTasks){
                    projectTaskData.status=firstTaskStatus
                 }
                 else{
                   projectTaskData.status=1
                 }
                }
                else{
                    projectTaskData.status=1 
                }
                    // Notification
                    console.log("#############projecttask",projectTaskData);
                    let resultStatus = await Project.updateProject(request.body.projectId,projectTaskData);
                    let notificationMsg = `The job task"${project[0].name}" has been deactivated.`;
                    let notificationUrl = "job";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id:project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }

                    reply.send({ status: 4, message: `The job"${project[0].name}" has been deleted!` })
                }
                else {
                    reply.send({ status: 5, message: "Unable to deactivate the job!" })
                }
            }
        }
        else {
            console.log("Error................")
            reply.send({ status: 500, message: "Error!" })
        }
    }
    catch (error) {
        console.log("#################errOR",error);
        reply.status(500).send({ message: "Server error"+error })
    }
}
const deleteDesignOrderProjectSubTask = async (request, reply) => {
    try {
        let { id, status,taskId,projectId } = request.body;
        let currentDate = Math.round(moment().valueOf() / 1000);
        if (!empty(id)) {
            let project = await ProjectTask.getProjectSubTaskById(id)

            if (status == 2) {
                let deleted = await ProjectTask.deleteProjectSubTask(id);

                if (deleted) {
                    // // Notification
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      let project = {};
                      project.complete=averageCompletion
                      let result = await ProjectTask.updateProjectTask(project,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const firstTaskStatus = allSubtask[0]?.status;
                      console.log("TaskStatus----------------",firstTaskStatus);
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=firstTaskStatus
                     }
                     else{
                       projectTask.status=1
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    let notificationMsg = `The job   "${project[0].name}" has been deleted.`;
                    let notificationUrl = "projects/view-project-task/";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 1, message: `The job  "${project[0].name}" has been deleted successfully!` })
                }
                else {
                    reply.send({ status: 0, message: `Unable to delete the job!` })
                }
            }
            else if (status == 1) {

                let deleted = await ProjectTask.updateProjectSubTask(id, { status: status })

                if (deleted) {
                    // // Notification
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      let project = {};
                      project.complete=averageCompletion
                      let result = await ProjectTask.updateProjectTask(project,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === 3);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=3
                     }
                     else{
                       projectTask.status=1
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    let notificationMsg = `The job task "${project[0].name}" has been deactivated.`;
                    let notificationUrl = "jobs";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }
                    reply.send({ status: 2, message: `The job task "${project[0].name}" has been made to active!` })
                }
                else {
                    reply.send({ status: 3, message: "Unable to activate the job task!" })
                }
            }
            else if (status == 0) {
                let deleted = await ProjectTask.updateProjectSubTask({ status: status }, id);

                if (deleted) {
                    let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                        taskId,userType=1,
                      );
                     console.log("###########ProjectSuub",projectSubTask); 
                      const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletion = sumCompletion / projectSubTask.length;
                      console.log("###########sumCompletion",projectSubTask); 
                      console.log("###########averageCompletion",averageCompletion); 
                      const firstSubTaskStatus = projectSubTask[0]?.status;
                    
                      const subTasksComplete = projectSubTask.filter(task => task.status === 3);
                      const subTasksNew = projectSubTask.filter(task => task.status === 1);
                      let completion=0
                                  if(!empty(subTasksComplete)){
                                    let data=100/projectSubTask.length
                                    completion=data*subTasksComplete.length
                                  }
                                 else{
                                    completion=0
                                 }  
                      const tasksWithStatusCompleted = projectSubTask.every(task => task.status === firstSubTaskStatus);
                    
                      let projectData = {};
                      projectData.complete=completion
                      if(!empty(projectSubTask)){
                        if(tasksWithStatusCompleted){
                            projectData.status=firstSubTaskStatus
                         }
                         else{
                            projectData.status=subTasksNew?.length>0?1:2
                         }
                      }
                      else{
                        projectData.status=1
                      }
                     
                     console.log("###########projectData",projectData); 
                      let result = await ProjectTask.updateProjectTask(projectData,taskId);
                      
                      let allSubtask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
                      const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
                      const averageCompletionTask = sumCompletionTask / allSubtask.length;
                      const firstTaskStatus = allSubtask[0]?.status;
                      const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
                      const tasksNew = allSubtask.filter(task => task.status === 1);
                      let projectTask = {};
                      projectTask.completion=averageCompletionTask
                      if(tasksWithStatusCompletedTasks){
                        projectTask.status=firstTaskStatus
                     }
                     else{
                       projectTask.status=tasksNew?.length>0?1:2
                     }
                      let resultStatus = await Project.updateProject(projectId,projectTask);
                    // Notification
                    let notificationMsg = `The job task"${project[0].name}" has been deactivated.`;
                    let notificationUrl = "jobs";

                    let adminIds = await Admin.getAllAdminIds();
                    let notificationData = {};

                    for (const adminId of adminIds) {

                        const incrementResult = await Admin.incrementField(adminId, "noti_count", 1);

                        notificationData = {
                            user_id: adminId,
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: project[0].userid,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);

                    }

                    reply.send({ status: 4, message: `The job"${project[0].name}" has been Deleted!` })
                }
                else {
                    reply.send({ status: 5, message: "Unable to deactivate the projet!" })
                }
            }
        }
        else {
            console.log("Error................")
            reply.send({ status: 500, message: "Error!" })
        }
    }
    catch (error) {
        console.log("Error................",error)
        reply.status(500).send({ message: "Server error"+error })
    }
}
const updatateProjectSubTaskStatus = async (req, reply) => {
    try {
        
        let { status, taskId, userId,task,projectId ,projectCategory,request_id} = req.body
        let currentDate = moment().unix();
        let projectTask = {}
        projectTask['status'] = status;
        let projectTaskDetails = await ProjectTask.getProjectSubTaskById(taskId)
        console.log('projectTaskDetailsssss', projectTaskDetails)
        const updated = await ProjectTask.updateProjectSubTask(projectTask, taskId);

        // Stopwatch logic

        console.log("##############Update tr",updated);
        if (updated) {
            let updatedSubTask = await ProjectTask.getProjectSubTaskById(taskId)
            let projectSubTask = await ProjectTask.getAllProjectSubTaskBytaskId(
                task,userType=1,
              );
              console.log("projectSubTask-------------",projectSubTask)
              const tasksWithStatusCompleted = projectSubTask.every(task => task.status === status);
              const subTasksComplete = projectSubTask.filter(task => task.status === 3);
              console.log("task with-------------",subTasksComplete)
              let completion=0
              if(!empty(subTasksComplete)){
                let data=100/projectSubTask.length
                completion=data*subTasksComplete.length
              }
             else{
                completion=0
             }
              console.log("task with-------------",completion)
              const subTasksNew = projectSubTask.filter(task => task.status === 1);
            //   const sumCompletion = projectSubTask.reduce((acc, task) => acc + task.complete, 0);
            //   const averageCompletion = sumCompletion / projectSubTask.length;
              let project = {};
               project.complete=completion
             if(tasksWithStatusCompleted){
                 project.status=status
              }
            //   else{
            //     project.status=subTasksNew?.length>0?1:2
            //   }
              console.log("###########Status",project);
              let result = await ProjectTask.updateProjectTask(project,task);
             
              let allTask=await ProjectTask.getAllProjectTasks(projectId,userType=1)
             const sumCompletionTask = allTask.reduce((acc, task) => acc + task.complete, 0);
             const averageCompletionTask = sumCompletionTask / allTask.length;
             const tasksWithStatusCompletedTasks = allTask.every(task => task.status === status);
             let taskCompleted=allTask.some(task => task.status === status);
             const TasksNew = allTask.filter(task => task.status === 1);
             let allTasksComplete = allTask.every(task => task.status === 1);

             console.log("#################AllTaskComplete 1",taskCompleted);
             console.log("#################AllTaskComplete 2",allTasksComplete);
             console.log("#################allTask",allTask);
             console.log("#################sumCompletionTask",sumCompletionTask);
             console.log("#################averageCompletionTask",averageCompletionTask);



// const isTaskCompleted = (task) => task.status === 3;

// let completedTasksCount = allTask.filter(isTaskCompleted).length;

// let pendingTasks = allTask.filter(task => task.status !== 3);

// if (
//   pendingTasks.length === 1 &&
//   pendingTasks[0].subtask_count - pendingTasks[0].subtask_completed_count === 1
//   && status==3
// ) {
//   console.log("One subtask pending, all other tasks completed");
//   const response = await axios.post(`http://localhost:4000/webservice/installation/convert-job-to-installation`,{selectedIds:projectId,userId:userId})
// }
            let projectTaskData = {};
            projectTaskData.completion=averageCompletionTask

            const computedProjectStatus = tasksWithStatusCompletedTasks
              ? Number(status)
              : (TasksNew?.length > 0 ? 1 : 2);

            const currentProject = await Project.getProjectById(projectId);
            const isEstimateJob = Number(currentProject?.is_estimate_job || 0) === 1;

            // Apply "no status regression" only for sales-order jobs.
            if (!isEstimateJob) {
              const currentProjectStatus = Number(currentProject?.status ?? 0);
              projectTaskData.status =
                computedProjectStatus < currentProjectStatus
                  ? currentProjectStatus
                  : computedProjectStatus;
            } else {
              projectTaskData.status = computedProjectStatus;
            }
             
           let resultStatus = await Project.updateProject(projectId,projectTaskData);

           let updatedTask=await ProjectTask.getAllProjectTasks(projectId,userId,userType=1)

           console.log('updatedTask',updatedTask)
           const readyForInstallation = updatedTask.every(task => task.status === 3);

        //    let resultStatus = await Project.updateProject(projectId,projectTaskData);
           

                if (readyForInstallation) {
                console.log('All tasks completed',readyForInstallation);
                } else {
                console.log('Some tasks are not completed',readyForInstallation);
                }

              console.log("##################Task stattus",tasksWithStatusCompleted);
            let notificationMsg = `The status of the Job Sub Task "${projectTaskDetails[0]['name']}" has been Updated`
            let notificationUrl = "projects/view-project-sub-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }

                 if(projectCategory && projectCategory ==12){
                   const updateRequestTable = await Request.updateRequets(request_id,{isReview :2})

                   let requestData = await Request.getRequestById(request_id);
              

                    let requestPartners = await RequestPartner.getRequestPartnerByIds({}, request_id)
                    let reqActivityMsg = "✅ Job has been completed and sent for review"
                    let notificationMsg = `✅ The Sales Order ${requestData[0].name} has been completed and sent for review.`;
                    let notificationUrl = `request/view/${request_id}`;

                    const currentDate = moment().unix();  
                    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 notificationData = {};
                    if (requestPartners.length > 0) {
                        for (const reqId of requestPartners) {
                        console.log("$$$$$$$$$$$$$", reqId);
                        const incrementResult = await Admin.incrementField(reqId['id'], "noti_count", 1);

                        notificationData = {
                            user_id: reqId['id'],
                            url: notificationUrl,
                            timestamp: currentDate,
                            message: notificationMsg,
                            status: 1,
                            from_id: userId,
                        };

                        const addNotificationResult = await Admin.addNotification(notificationData);
                        }
                    }

                     let requestActivity = {}
                        requestActivity['request_id'] = request_id;
                        requestActivity['activity'] = reqActivityMsg
                        requestActivity['added_by'] = userId
                        requestActivity['timestamp'] = currentDate
                        requestActivity['status'] = 1
                        let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            }


            reply.send({ status: 1,updatedStatus:updatedSubTask[0]?.status, message: "Job Sub Task status  has been Updated",readyForInstallation });
        }
        else {
            reply.send({ status: 0, message: "Failed to update job sub task status ",readyForInstallation:false });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }


}

const checkReadyForInstallationStatus = async (req, reply) => {
    try {
      const { projectId, userId, projectCategory, request_id } = req.body;
  
      const allTasks = await ProjectTask.getAllProjectTasks(projectId, userId, 1);
      const pendingTasks = allTasks.filter(task => task.status !== 3);
  
      let readyForInstallation = false;
  
      if (
        pendingTasks.length === 1 &&
        (pendingTasks[0].subtask_count - pendingTasks[0].subtask_completed_count) === 1
      ) {
        readyForInstallation = true;
      }
    //   if(projectCategory ==12){
    //       const updateRequestTable = await Request.updateRequets(request_id,{isReview :0})
    //     }
      reply.send({ status: 1, readyForInstallation });
    } catch (error) {
      reply.status(500).send({ status: 0, message: "Server error: " + error });
    }
  };  
  

const addProjectTaskAttachments=async(req,reply)=>{
    let {userId,userType,attachments,projectId,taskId}=req.body
   
   
    const urlObjects = [];
    for (const key in attachments) {
        if (attachments.hasOwnProperty(key)) {
            const urls = attachments[key];
            urls.forEach(url => {
                urlObjects.push({ url, extension: key });
            });
        }
    }
   
   
    console.log("$$$$$$$$$$URL",urlObjects.length);
    let inserted=""
    for(let i=0;i<urlObjects.length;i++){
        let data={}
        if(urlObjects[i].url){
            data.userid=userId,
            data.task_id=taskId,
            data.project_id=projectId,
            data.file_url=urlObjects[i].url
            data.extension=urlObjects[i].extension,
            data.timestamp=moment().unix()
            console.log(data,'=====')
            inserted=await ProjectTask.addAttachments(data)
        }
        
    }
    if(inserted){
       
            let notificationMsg = "Attachments added successfully"
            let notificationUrl = "projects/view-project-sub-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }

        reply.send({status:1,message:"Attachments added successfully"})
    }
    else{
        reply.send({status:0, message:"Failed to add attachments"})
    }
}
const fetchProjectTaskAttachments=async(req, reply)=>{
    let {projectId,taskId,mirrored,targetFacilityId}=req.body
    if(mirrored && targetFacilityId){
        const targetFacility = filteredSignwiseInstalations.find(
            f => f.id === Number(targetFacilityId)
        );
        if (!targetFacility?.url) return null;
        const projectResponse = await axios.post(
            `${targetFacility.url}project-task/fetch-project-attachments`,
            {
                projectId :projectId,
                taskId :taskId,
            }
        );

        if (projectResponse?.data) {
            const mirroredData = projectResponse.data;
            reply.send({status:1, attachments:mirroredData?.attachments})
        }
        else{
            reply.send({status:0, message:"Failed to fetch attachments"})
        }
    }
    // normal case
    let attachments=await ProjectTask.getAttachments(projectId,taskId)
    if(attachments){
        reply.send({status:1, attachments:attachments})
    }
    else{
        reply.send({status:0, message:"Failed to fetch attachments"})
    }
}
const deleteProjectTaskAttachments=async(req, reply)=>{
    let {userId,userType,attachments,projectId, taskId}=req.body
    let deleted=await ProjectTask.deleteProjectTaskAttachment(attachments)
    if(deleted){
        let notificationMsg = "Attachments deleted in the job"
            let notificationUrl = "projects/view-project-sub-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }
        reply.send({status:1, message:"Attachments deleted successfully"})
    }
    else{
        reply.send({status:0, message:"Failed to delete attachments"})
    }
}
const addProjectAttachments=async(req,reply)=>{
    let {userId,userType,attachments,projectId,taskId,request_id,designOrderId}=req.body
    const urlObjects = [];
    for (const key in attachments) {
        if (attachments.hasOwnProperty(key)) {
            const urls = attachments[key];
            urls.forEach(url => {
                urlObjects.push({ url, extension: key });
            });
        }
    }
    console.log("$$$$$$$$$$URL",urlObjects);
    let inserted=""
    for(let i=0;i<urlObjects.length;i++){
        let data={}
        if(urlObjects[i].url){
            data.userid=userId,
          
            data.project_id=projectId,
            data.file_url=urlObjects[i].url
            data.extension=urlObjects[i].extension,
            data.file_type=urlObjects[i].extension,
            data.timestamp=moment().unix()
            inserted=await ProjectTask.addProjectAttachments(data)
            console.log("inserted",inserted)

            // Convert project PDF attachments to images for editing (estimate project)
            // Always let the helper decide if it's really a PDF (handles file_type = 'other')
            // if (inserted) {
            //     try {
            //         await convertPdfToPngHelper(inserted, getProjectAttachmentByIdForConversion, 'estimate_project');
            //         console.log(`PDF conversion completed for project attachment ID: ${inserted}`);
            //     } catch (conversionError) {
            //         console.error(`Error converting PDF for project attachment ${inserted}:`, conversionError);
            //     }
            // }
        }
        
    }
    if(inserted){
       
            let notificationMsg = "Attachments added successfully "
            let notificationUrl = "projects/view-project-sub-task/" + taskId;
            let notificationData = {};

            

            let requestActivity = {}
            requestActivity['request_id'] = request_id;
            requestActivity['activity'] = notificationMsg;
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }

        reply.send({status:1,message:"Attachments added successfully"})
    }
    else{
        reply.send({status:0, message:"Failed to add attachments"})
    }
}
const fetchProjectAttachments=async(req, reply)=>{
    let {projectId}=req.body
    let attachments=await ProjectTask.getProjectAttachments(projectId)
    if(attachments){
        reply.send({status:1, attachments:attachments})
    }
    else{
        reply.send({status:0, message:"Failed to fetch attachments"})
    }
}
const fetchAllProjectAttachments=async(req, reply)=>{
    let {projectId,showAllAttachments,isMirrored,targetFacilityId,originRequestId}=req.body

    // for mirroring the attachments from the other facility
    if (isMirrored && targetFacilityId && originRequestId) {
        const targetFacility = filteredSignwiseInstalations.find(
            f => f.id === Number(targetFacilityId)
        );
        if (!targetFacility?.url) return null;
        const targetProjectId = await SplitManagementModel.getProjectIdFromOtherFacility(targetFacilityId, originRequestId);

        // 🔹 STEP 2: Fetch project using resolved ID
        const projectResponse = await axios.post(
            `${targetFacility.url}project-task/fetch-project-attachments`,
            {
                projectId :targetProjectId,
                showAllAttachments:showAllAttachments,
            }
        );

        if (projectResponse?.data) {
            const mirroredData = projectResponse.data;
            reply.send({status:1, attachments:mirroredData?.attachments})
        }
        else{
            reply.send({status:0, message:"Failed to fetch attachments"})
        }
    }
    
    let attachments=await ProjectTask.getAllProjectAttachments(projectId)
    if(showAllAttachments){
    let allTasks = await ProjectTask.fetAllTaskByProjectId(projectId)
    let taskAttachments = []
    for(const task of allTasks){
        let taskAttachmentsRes = await ProjectTask.getAttachments(projectId,task.ID)
        taskAttachments = [...taskAttachments, ...taskAttachmentsRes]
    }
    attachments = [...attachments, ...taskAttachments]
}
    if(attachments){
        reply.send({status:1, attachments:attachments})
    }
    else{
        reply.send({status:0, message:"Failed to fetch attachments"})
    }
}
const deleteProjectAttachments=async(req, reply)=>{
    let {userId,userType,attachments,projectId, taskId}=req.body
    let deleted=await ProjectTask.deleteProjectAttachment(attachments)
    if(deleted){
        let notificationMsg = "Attachments deleted in the job"
            let notificationUrl = "projects/view-project-sub-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }
        reply.send({status:1, message:"Attachments deleted successfully"})
    }
    else{
        reply.send({status:0, message:"Failed to delete attachments"})
    }
}

const addStaffTaskTimelog = async (req, reply) => {
    try{
        const {checkedItems,taskId, projectId, checkedInstallations, driverUserID,
             userId,now, noSubTask, isDriver,userType,createInstallLabour,selectedService} = req.body
             console.log('reqqqqqqqqqqqqqqqqq',req.body)
        const subtaskIds = checkedItems?.join(',');
        const installationIds = checkedInstallations?.join(',');
        let currentDate = Math.round(moment().valueOf() / 1000);
        let addStaffTaskTimelog = null
        console.log("clockin function 1 addStaffTaskTimelog",checkedInstallations)
        if(isDriver){
            for(const instId of checkedInstallations){
                const installationData = await Installation.fetchApointmentById(instId);
                console.log('installationData======',installationData)
                let data = {}
                data.job_id = projectId || installationData[0]?.project_id || null
                data.task_id = taskId || null
                data.sub_task_id = subtaskIds || null
                data.installation_id = installationIds|| null
                data.noSubTask = noSubTask ? 1 : 0
                data.isDriver = isDriver ? 1 : 0
                data.user_id = isDriver ? driverUserID : userId
                data.start_time = now ? now : currentDate
                data.status = 1
                data.service_id = selectedService
                addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
            }
        }else{
            let data = {}
            data.job_id = projectId || null
            data.task_id = taskId || null
            data.sub_task_id = subtaskIds || null
            data.installation_id = installationIds|| null
            data.noSubTask = noSubTask ? 1 : 0
            data.isDriver = isDriver ? 1 : 0
            data.user_id = isDriver ? driverUserID : userId
            data.start_time = now ? now : currentDate
            data.status = 1
            data.service_id = selectedService
             addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
        }

        if(isDriver){
            for(const instId of checkedInstallations){
                const installationData = await Installation.fetchApointmentById(instId);
                if(installationData && installationData?.length > 0){
                    let requestId = installationData[0]?.request_id;
                    let fetchedRequestData = await Request.getRequestById(requestId);
                    let laborCostServices = fetchedRequestData[0]?.labour_cost_services;
                    console.log('laborCostServices-------',laborCostServices)
                    let isHavingLaborInstallService = false;
                    if (laborCostServices) {
                        laborCostServices = laborCostServices.split(',').map(i => i.trim());
                        isHavingLaborInstallService = laborCostServices.includes('10');
                    }else{
                        laborCostServices = [];
                    }
                    if (!isHavingLaborInstallService){
                        laborCostServices.push('10');
                        let updatedServices = laborCostServices.join(',');
                        let newRequestData = {
                            labour_cost_services: updatedServices
                        };
                        let updateReqID = await Request.updateRequets(requestId, newRequestData);
                    }
                    let serviceResponse = await Request.getRequestServices(requestId,10);
                    if (!serviceResponse || serviceResponse.length === 0) {
                        const id = 10
                        const serviceData = await Product.getLabourCostServicesById(id);
                        let requestProduct = {};
                        requestProduct['product_index'] = 0
                        requestProduct['request_id'] = requestId
                        requestProduct['labour_cost_service_id'] = id,
                        requestProduct['recipe_id'] = null,
                        requestProduct['product_id'] = null,
                        requestProduct['qty'] = 0,
                        requestProduct['unit_cost'] = serviceData[0]?.total_cost || 0,
                        requestProduct['markup'] = 0,
                        requestProduct['total_cost'] = 0
                        requestProduct['rfp'] = 0
                        requestProduct['jobcost_unit_cost'] = 0
                        requestProduct['jobcost_quantity'] = 0
                        requestProduct['jobcost_total_cost'] = 0
                        let response = await Request.addRequestServices(requestProduct)
                    }
                }
            }
        }

        if(addStaffTaskTimelog){
            reply.send({status:1, message:"Timelog for task added successfully",result:'add'});
        }else{
            reply.send({status:0, message:"Failed to add timelog"});
        }
    }catch(error){
        console.log("Add staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to add timelog",error:error});
    }
}

const addStaffTaskTimelogDriverAndInstaller = async (req, reply) => {
    try{
        const {checkedItems,taskId, projectId, checkedInstallations, driverUserID, userId,now, noSubTask, isDriver} = req.body
        const subtaskIds = checkedItems?.join(',');
        const installationIds = checkedInstallations?.join(',');
        let currentDate = Math.round(moment().valueOf() / 1000);
        let addStaffTaskTimelog = null
        console.log("clockin function 2 addStaffTaskTimelogDriverAndInstaller")

         const installationData = await Installation.fetchInstallationDataById(checkedInstallations[0]);
        console.log('installationDataaddStaffTaskTimelogDriverAndInstaller 2',installationData)
        // if(isDriver){
        //for driver
            // for(const instId of checkedInstallations){
            //     const installationData = await Installation.fetchApointmentById(instId);
            //     console.log('installationDataaddStaffTaskTimelogDriverAndInstaller',installationData)
            //     let data = {}
            //     data.job_id = projectId || installationData[0]?.project_id || null
            //     data.task_id = taskId || null
            //     data.sub_task_id = subtaskIds || null
            //     data.installation_id = installationIds|| null
            //     data.noSubTask = noSubTask ? 1 : 0
            //     data.isDriver = isDriver ? 1 : 0
            //     data.user_id = isDriver ? driverUserID : userId
            //     data.start_time = now ? now : currentDate
            //     data.status = 1
            //     addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
            // }

             for (const driver of installationData.driverData) {
        const data = {
          job_id:projectId || installationData?.project_id || null,
          task_id: taskId || null,
          sub_task_id: subtaskIds || null,
          installation_id: installationIds || null,
          noSubTask: noSubTask ? 1 : 0,
          isDriver: 1,
          user_id: driver.user_id,
          start_time: now || currentDate,
          status: 1
        };
        addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
      }
        // }
        // else{
             //team member
               const installer = installationData.teamData[0];
             const data = {
          job_id :installationData?.project_id,
          task_id: taskId || null,
          sub_task_id: subtaskIds || null,
          installation_id: installationIds || null,
          noSubTask: noSubTask ? 1 : 0,
          isDriver: 0,
          user_id: installer.user_id,
          start_time: now || currentDate,
          status: 1
        };
        addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
        // }

        // if(isDriver){
            for(const instId of checkedInstallations){
                const installationData = await Installation.fetchApointmentById(instId);
                if(installationData && installationData?.length > 0){
                    let requestId = installationData[0]?.request_id;
                    let fetchedRequestData = await Request.getRequestById(requestId);
                    let laborCostServices = fetchedRequestData[0]?.labour_cost_services;
                    console.log('laborCostServices-------',laborCostServices)
                    let isHavingLaborInstallService = false;
                    if (laborCostServices) {
                        laborCostServices = laborCostServices.split(',').map(i => i.trim());
                        isHavingLaborInstallService = laborCostServices.includes('10');
                    }else{
                        laborCostServices = [];
                    }
                    if (!isHavingLaborInstallService){
                        laborCostServices.push('10');
                        let updatedServices = laborCostServices.join(',');
                        let newRequestData = {
                            labour_cost_services: updatedServices
                        };
                        let updateReqID = await Request.updateRequets(requestId, newRequestData);
                    }
                    let serviceResponse = await Request.getRequestServices(requestId,10);
                    if (!serviceResponse || serviceResponse.length === 0) {
                        const id = 10
                        const serviceData = await Product.getLabourCostServicesById(id);
                        let requestProduct = {};
                        requestProduct['product_index'] = 0
                        requestProduct['request_id'] = requestId
                        requestProduct['labour_cost_service_id'] = id,
                        requestProduct['recipe_id'] = null,
                        requestProduct['product_id'] = null,
                        requestProduct['qty'] = 0,
                        requestProduct['unit_cost'] = serviceData[0]?.total_cost || 0,
                        requestProduct['markup'] = 0,
                        requestProduct['total_cost'] = 0
                        requestProduct['rfp'] = 0
                        requestProduct['jobcost_unit_cost'] = 0
                        requestProduct['jobcost_quantity'] = 0
                        requestProduct['jobcost_total_cost'] = 0
                        let response = await Request.addRequestServices(requestProduct)
                    }
                }
            }
        // }

        if(addStaffTaskTimelog){
            reply.send({status:1, message:"Timelog for task added successfully",result:'add'});
        }else{
            reply.send({status:0, message:"Failed to add timelog"});
        }
    }catch(error){
        console.log("Add staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to add timelog",error:error});
    }
}

const addInstallerTaskTimelog = async (req, reply) => {
    try{
        const {checkedItems,taskId, projectId, checkedInstallations, driverUserID,
             userId,now, noSubTask, isDriver,userType,createInstallLabour,hasAcceptedRoutesPermission} = req.body
             console.log('reqqqqqqqqqqqqqqqqq',req.body)
        const subtaskIds = checkedItems?.join(',');
        const installationIds = checkedInstallations?.join(',');
        let currentDate = Math.round(moment().valueOf() / 1000);
        let addStaffTaskTimelog = null
        console.log("clockin function 1 addStaffTaskTimelog",checkedInstallations)
        
            for(const instId of checkedInstallations){
                const installationData = await Installation.fetchApointmentById(instId);
                const getSingleRequestService10 = await Request.getSingleRequestService10(installationData[0]?.request_id)
                const inst = installationData[0];    
                console.log('installationData======',installationData)
                let teamIds = [];
                if(hasAcceptedRoutesPermission){
                    teamIds = [...new Set([userId, ...(inst?.team_id || '').split(',').map(id => id.trim()).filter(Boolean)])];
                }else{
                    teamIds = [...new Set( (inst?.team_id || '').split(',').map(id => id.trim()).filter(Boolean))];
                }
                const base = {
                        job_id:           projectId    ?? inst?.project_id ?? null,
                        task_id:          taskId       ?? null,
                        sub_task_id:      subtaskIds   ?? null,
                        installation_id:  installationIds ?? null,
                        noSubTask:        noSubTask ? 1 : 0,
                        isDriver:         isDriver  ? 1 : 0,
                        start_time:       now ?? currentDate,
                        status:           1,
                        service_id: getSingleRequestService10?.id || null,
                    };

               for (const teamUserId of teamIds) {
    const data = { ...base, user_id: teamUserId };
   addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
  }
            }
        

     
            for(const instId of checkedInstallations){
                const installationData = await Installation.fetchApointmentById(instId);
                if(installationData && installationData?.length > 0){
                    let requestId = installationData[0]?.request_id;
                    let fetchedRequestData = await Request.getRequestById(requestId);
                    let laborCostServices = fetchedRequestData[0]?.labour_cost_services;
                    console.log('laborCostServices-------',laborCostServices)
                    let isHavingLaborInstallService = false;
                    if (laborCostServices) {
                        laborCostServices = laborCostServices.split(',').map(i => i.trim());
                        isHavingLaborInstallService = laborCostServices.includes('10');
                    }else{
                        laborCostServices = [];
                    }
                    if (!isHavingLaborInstallService){
                        laborCostServices.push('10');
                        let updatedServices = laborCostServices.join(',');
                        let newRequestData = {
                            labour_cost_services: updatedServices
                        };
                        let updateReqID = await Request.updateRequets(requestId, newRequestData);
                    }
                    let serviceResponse = await Request.getRequestServices(requestId,10);
                    if (!serviceResponse || serviceResponse.length === 0) {
                        const id = 10
                        const serviceData = await Product.getLabourCostServicesById(id);
                        let requestProduct = {};
                        requestProduct['product_index'] = 0
                        requestProduct['request_id'] = requestId
                        requestProduct['labour_cost_service_id'] = id,
                        requestProduct['recipe_id'] = null,
                        requestProduct['product_id'] = null,
                        requestProduct['qty'] = 0,
                        requestProduct['unit_cost'] = serviceData[0]?.total_cost || 0,
                        requestProduct['markup'] = 0,
                        requestProduct['total_cost'] = 0
                        requestProduct['rfp'] = 0
                        requestProduct['jobcost_unit_cost'] = 0
                        requestProduct['jobcost_quantity'] = 0
                        requestProduct['jobcost_total_cost'] = 0
                        let response = await Request.addRequestServices(requestProduct)
                    }
                }
            }
    

        if(addStaffTaskTimelog){
            reply.send({status:1, message:"Timelog for task added successfully",result:'add'});
        }else{
            reply.send({status:0, message:"Failed to add timelog"});
        }
    }catch(error){
        console.log("Add staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to add timelog",error:error});
    }
}

const addTimesheet = async (req, reply) => {
    try{
        const {subtask,taskId, projectId, teamUserId, start, end,user_id, staffHourlyRate, teamId, isDesignJob} = req.body
        const subtaskIds = subtask && subtask.length > 0 ? subtask.join(',') : null;
        let notificationMsg=''
        let currentDate = Math.round(moment().valueOf() / 1000);
        const elapsedTimeSeconds = end - start;
        const elapsedTimeHours = elapsedTimeSeconds / 3600;
        const totalAmount = staffHourlyRate * elapsedTimeHours  
        
        // Check if project is a design order
        let isDesignOrder = false;
        if (isDesignJob !== undefined) {
            isDesignOrder = isDesignJob;
        } else {
            // Fallback: check if projectId exists in design_orders table
            const designOrder = await Request.getDesignOrderByIdNew(projectId);
            isDesignOrder = designOrder && designOrder.length > 0;
        }
        
        // Get project details to check category and request_id (only for regular projects)
        let projects = null;
        if (!isDesignOrder) {
            projects = await Project.getProjectById(projectId);
        }
        
        // Get task details to check if it's manually added (only for regular projects)
        let taskDetails = null;
        let isTaskManuallyAdded = false;
        if (taskId && !isDesignOrder) {
            taskDetails = await ProjectTask.getProjectTaskById(taskId);
            if (taskDetails?.length > 0) {
                isTaskManuallyAdded = taskDetails[0].is_manually_added === 1 || taskDetails[0].is_manually_added === "1";
                console.log('🔍 Task manually added check:', isTaskManuallyAdded);
            }
        }
        
        // Get installLabourService for Time & Material (category 12) projects (only for regular projects)
        let installLabourService = null;
        if(!isDesignOrder && projects?.project_category == 12){
            installLabourService = await Request.getSingleRequestService10(projects?.request_id);
            console.log('requestService10', installLabourService)
        }
        
        // Get productTaskServiceId from task services if task is NOT manually added (only for regular projects)
        let productTaskServiceId = null;
        if (taskId && !isTaskManuallyAdded && !isDesignOrder) {
            const getServicesFromTask = await ProjectTask.getServicesFromProductTask(taskId);
            console.log('getServicesFromTask+++', getServicesFromTask)
            productTaskServiceId = getServicesFromTask?.requestServices[0]?.id || getServicesFromTask?.projectTask?.customer_order_product_id;
        }
        
        // Determine finalServiceId based on task type (only for regular projects)
        let finalServiceId = null;
        if (!isDesignOrder) {
        if (isTaskManuallyAdded) {
            // For manually added tasks, always set service_id to null
            finalServiceId = null;
            console.log('🔧 Task is manually added, setting service_id to null');
        } else {
            // For non-manually added tasks, use fallback logic
            finalServiceId = installLabourService?.id || productTaskServiceId || null;
            }
        }
        console.log('finalServiceIdfinalServiceId', finalServiceId)
        
        let addStaffTaskTimelog = false;
        
        if (isDesignOrder) {
            // Handle design order timelog
            let timelogData = {
                design_order_id: projectId,
                task_id: taskId ? Number(taskId) : null,
                sub_task_id: subtaskIds || null,
                user_id: teamUserId,
                start_time: start,
                end_time: end,
                status: 1,
                noSubTask: 0
            };
            const timelogId = await Request.addDesignOrderStaffTaskTimelog(timelogData);
            addStaffTaskTimelog = timelogId ? true : false;
        } else {
            // Handle regular project timelog
        let data = {}
        data.job_id = projectId
            data.task_id = taskId ? Number(taskId) : null
        data.sub_task_id = subtaskIds || null
        data.user_id = teamUserId
        data.start_time = start
        data.end_time = end
        data.status = 1
        data.service_id = finalServiceId
            addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data)
        }
        
        if(addStaffTaskTimelog){
            let insertedstatus = false;
            
            if (isDesignOrder) {
                // Handle design order payout
                let payoutData = {
                    design_order_id: projectId,
                    task_id: taskId ? Number(taskId) : null,
                    log_id: subtaskIds || null,
                    team: teamId,
                    paid_at: start,
                    end_date: end,
                    hours: elapsedTimeHours,
                    amount: totalAmount,
                    timestamp: moment().unix(),
                    is_time_tracking: 1,
                    added_by: user_id,
                    status: user_id === 1 ? 1 : 5,
                    is_auto_pay: 1
                };
                insertedstatus = await Request.addDesignOrderPayOut(payoutData);
            } else {
                // Handle regular project payout
            let data = {
                project_id: projectId,
                    task_id: taskId ? Number(taskId) : null,
                log_id: subtaskIds || null,
                timelog_id: addStaffTaskTimelog ? addStaffTaskTimelog : null,
                team: teamId,
                paid_at: currentDate,
                amount: totalAmount,
                timestamp: moment().unix(),
                is_time_tracking: 1,
                added_by: user_id,
                status:1,
                is_auto_pay:1,
                service_id: finalServiceId
            };
            insertedstatus = await JobCost.addPayOut(data)
            }
            
            if (insertedstatus) {
                if(subtask?.length > 0 && !isDesignOrder){
                    for(const data of subtask){
                        let updateData = {}
                        updateData['status'] = 0
                        await ProjectTask.updateLogStatus(updateData, data)
                    }
                }

                // ---- Keep request_services jobcost fields in sync (non design order projects) ----
                // Mirrors the reconciliation approach used in updateStaffTaskTimelog:
                // - fetch all staff timelogs for the project
                // - match logs by service_id === request_services.id
                // - recompute total hours + total payout per service and update request_services
                if (!isDesignOrder) {
                    try {
                        let projectTaskDetails = null;
                        let requestServices = null;
                        let stafftimelogs = null;

                        if (taskId) {
                            projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
                        } else if (projectId) {
                            projectTaskDetails = await ProjectTask.getProjectDataById(projectId);
                        }

                        if (projectTaskDetails?.length > 0) {
                            projectTaskDetails = projectTaskDetails[0];
                            stafftimelogs = await ProjectTask.fetchStaffTimelogsByProjectId(null, null, projectTaskDetails.project_id);
                            requestServices = await Request.getRequestServices(
                                projectTaskDetails.request_id,
                                false,
                                false,
                                false,
                                projectTaskDetails?.project_category
                            );

                            let hasHandledLabour10 = false;

                            if (requestServices?.length > 0) {
                                for (const item of requestServices) {
                                    // Only update once for labour install service (ID = 10)
                                    if (item.labour_cost_service_id === 10 && hasHandledLabour10) continue;
                                    if (item.labour_cost_service_id === 10) hasHandledLabour10 = true;

                                    if (!stafftimelogs) continue;

                                    const matchedTimelogs = stafftimelogs.filter(
                                        (log) => parseInt(log.service_id) === item.id
                                    );

                                    if (matchedTimelogs.length === 0) continue;

                                    // Sum hours from timelog durations
                                    let totalHours = 0;
                                    for (const log of matchedTimelogs) {
                                        const startMoment = moment.unix(log.start_time);
                                        const endMoment = log.end_time !== null ? moment.unix(log.end_time) : moment();
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        const logHours = duration.asHours();
                                        if (!isNaN(logHours)) totalHours += logHours;
                                    }

                                    // Sum payouts for this request service id (stored as payouts.service_id)
                                    const payoutData = await JobCost.getPayOutByServiceId(projectId, item.id);
                                    if (!payoutData || payoutData.length === 0) continue;

                                    const totalPayoutAmount = payoutData.reduce((total, p) => total + (p.amount || 0), 0);

                                    const data = {
                                        jobcost_quantity: totalHours,
                                        jobcost_unit_cost: item?.hourly_rate || 0,
                                        jobcost_total_cost: totalPayoutAmount,
                                        taken: 1
                                    };

                                    // Special handling for Time & Material (category 12) labour install service (10)
                                    if (projectTaskDetails?.project_category == 12 && item?.labour_cost_service_id === 10) {
                                        const installHours = totalHours?.toFixed(2);
                                        data.qty = installHours;
                                        data.total_cost = ((installHours || 0) * item.unit_cost);
                                    }

                                    await Request.updateRequestServices(data, item.id, item.request_id);
                                }

                                // Keep recipe taken flags consistent (same as updateStaffTaskTimelog)
                                await new Promise(resolve => setTimeout(resolve, 100));
                                const takenItems = await Request.getAllRecipeRequestServices(projectTaskDetails?.request_id);
                                if (takenItems?.some(item => item.taken === 1)) {
                                    await Request.updateAllRecipesTakenByRequestId(projectTaskDetails?.request_id);
                                }
                            }
                        }
                    } catch (err) {
                        console.log('⚠️ addTimesheet: failed to update request services jobcost fields:', err);
                    }
                }

                // ---- JobCost log (non design order projects) ----
                // Keep messaging consistent with updateStaffTaskTimelog so recipe/job costing screens have an audit trail.
                if (!isDesignOrder) {
                    try {
                        // Fetch the newly created timelog row to get staff_name (joined from users)
                        const createdLogs = await ProjectTask.fetchStaffTimelogsByProjectId(addStaffTaskTimelog, null, null);
                        const staffName = createdLogs?.[0]?.staff_name || `${teamUserId || ''}`.toString() || 'Staff';

                        const totalMinutes = Math.round(elapsedTimeHours * 60);
                        const hh = Math.floor(totalMinutes / 60);
                        const mm = totalMinutes % 60;

                        const taskName =
                            taskDetails?.[0]?.task_name ||
                            taskDetails?.[0]?.name ||
                            createdLogs?.[0]?.task_name ||
                            'N/A';

                        // Resolve subtask names from project_subtasks table
                        let subtaskLabel = 'N/A';
                        if (subtaskIds) {
                            const subtaskIdList = subtaskIds
                                .split(',')
                                .map((x) => parseInt(String(x).trim(), 10))
                                .filter((n) => !isNaN(n));
                            if (subtaskIdList.length > 0) {
                                const names = await Promise.all(
                                    subtaskIdList.map(async (id) => {
                                        const res = await ProjectTask.fetchSubTaskName(id);
                                        return res?.[0]?.sub_task_name || null;
                                    })
                                );
                                const cleaned = names.filter(Boolean);
                                subtaskLabel = cleaned.length > 0 ? cleaned.join(', ') : 'N/A';
                            }
                        }

                        let logMessage = '';
                        if (projects?.project_category == 12 && !isTaskManuallyAdded) {
                            logMessage = `'${staffName}' worked on labor install.`;
                        } else {
                            logMessage = `'${staffName}' worked ${hh}h ${mm}m on task '${taskName}' (subtask: '${subtaskLabel}').`;
                        }

                        await JobCost.addJobCostLog({
                            message: sanitizeLog(logMessage),
                            user_id: user_id,
                            timestamp: moment().unix(),
                            status: 1,
                            project_id: projectId
                        });
                    } catch (err) {
                        console.log('⚠️ addTimesheet: failed to add JobCost log:', err);
                    }
                }

                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(user_id,"noti_count",1);

                let notificationData_user = {
                    user_id: teamUserId,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: user_id,
                };
                const addNotificationResult_user = await Admin.addNotification(notificationData_user);
                let adminIds = await Admin.getAllAdminIds();
                let notificationData = {};
                for (const adminId of adminIds) {
                    if (adminId != teamUserId) {
                        const incrementResult = await Admin.incrementField(adminId,"noti_count",1);
                        notificationData = {
                        user_id: adminId,
                        url: notificationUrl,
                        timestamp: currentDate,
                        message: notificationMsg,
                        status: 1,
                        from_id: user_id,
                        };
                        const addNotificationResult = await Admin.addNotification(notificationData);
                    }
                }
            }
            reply.send({status:1, message:"Timelog for task added successfully",result:'add'})
        }else{
            reply.send({status:0, message:"Failed to add timelog"})
        }
    }catch(error){
        console.log("Add staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to add timelog", error: error.message})
    }
}


////////////////////////qb
const addJournalEntryToQuickBooks = async ({ amount,description,projectTypeQuickBookId,docNumber,requestId }) => {
  
  const token = await getNewAccessToken();
  const apiUrl = PRODUCTION
    ? `https://quickbooks.api.intuit.com/v3/company/${realmId}`
    : `https://sandbox-quickbooks.api.intuit.com/v3/company/${realmId}`;

  const date = moment().format('YYYY-MM-DD');


   let debitAccount = "Work In Progress";
   let creditAccount = "Split Labor";
   let debitAccountId = await findAccountIdByAcctNum(1014000)
   let creditAccountId =await findAccountIdByAcctNum(5081000)
//    let debitAccountId = await getAccountIdByName("Work In Progress (WIP) -Labor") 
//    let creditAccountId =await getAccountIdByName("Payroll Clearing") 
 let transactionCount = await Project.getTransactionCountByProjectId(null,requestId);
 let futureTransactionCount = Number(transactionCount) + 1;
 let journalNumber = docNumber + '-' + futureTransactionCount;

  const journalEntryData = {
    DocNumber: journalNumber,
    Line: [
      {
        Id: "1",
        Description: description,
        Amount: amount,
        DetailType: "JournalEntryLineDetail",
        JournalEntryLineDetail: {
          PostingType: "Debit",
          AccountRef: { value: debitAccountId, name: debitAccount },
          DepartmentRef: { value: departmentId },
          ClassRef: { value: projectTypeQuickBookId },
        }
      },
      {
        Id: "2",
        Description: description,
        Amount: amount,
        DetailType: "JournalEntryLineDetail",
        JournalEntryLineDetail: {
          PostingType: "Credit",
          AccountRef: { value: creditAccountId, name: creditAccount },
          DepartmentRef: { value: departmentId },
          ClassRef: { value: projectTypeQuickBookId },
        }
      }
    ],
    TxnDate: date,
    PrivateNote: `Auto journal entry for job costing`
  };

try {
    const response = await axios.post(`${apiUrl}/journalentry`, journalEntryData, {
        headers: {
          Authorization: `Bearer ${token}`,
          Accept: 'application/json',
          'Content-Type': 'application/json'
        }
      });
    
      console.log('✅ Journal entry posted:', response.data);
      const updateProject = await Project.updateProjectByRequestId(requestId, { qb_transaction_count: futureTransactionCount });
} catch (error) {
    console.error("❌ Error creating Journal Entry for final invoice:", err.response?.data || err.message);
    if (err.response?.data?.Fault?.Error) {
      console.error("QuickBooks Error Details:", err.response.data.Fault.Error);
    } else {
      console.error("Unexpected Error:", err);
    }
}
};


////////////////////////////
// olddddddd
// const updateStaffTaskTimelog = async (req, reply) => {
//     try{
//         const {checkedItems, taskId, projectId, checkedInstallations, driverUserID,
//              userId, isDriver, timeLogId, now, startTime, staffId, staffHourlyRate,userType,selectedService,
//             createInstallLabour} = req.body
//         let notificationMsg=''
//         let projectTaskDetails='';
//         let requestServices='';
//         let stafftimelogs='';
//         let newhours = 0;
//         let newhours1 = 0;
//         let hours = 0;
//         let laborInstallId = 10;
//         let installationIds = null;
//         let installationPayoutData = null
//         let nnpayoutData = null;
//         let nntotalPayoutAmount = null;
//           console.log("clockin function 3 updateStaffTaskTimelog")
//         if(checkedInstallations && checkedInstallations?.length > 0){
//             installationIds = checkedInstallations?.join(', ')
//         }
//         let currentDate = Math.round(moment().valueOf() / 1000);
//         const elapsedTimeSeconds = now - startTime;
//         const elapsedTimeHours = elapsedTimeSeconds / 3600;
//         const totalAmount = parseFloat((staffHourlyRate || 0) * elapsedTimeHours).toFixed(2);
//         console.log('elapsedTimeHourselapsedTimeHours--startTime',startTime)
//         console.log('elapsedTimeHourselapsedTimeHours--now',now)
//         console.log('elapsedTimeHourselapsedTimeHours--elapsedTimeHours',elapsedTimeHours)
//         console.log('elapsedTimeHourselapsedTimeHours--totalAmount',totalAmount)
//         console.log('elapsedTimeHourselapsedTimeHours--checkedItems',checkedItems)
        
      

  
     

//         let data = {}
//         data.end_time = now ? now : currentDate
//         const newUserId = isDriver ? driverUserID : userId
//         const updateResult = await ProjectTask.updateStaffTaskTimelog(data, taskId, projectId, checkedInstallations, newUserId, timeLogId,selectedService);
//         if(updateResult){
//             if(isDriver){
//                 for(const instId of checkedInstallations){
//                     const installationData = await Installation.fetchApointmentById(instId);
//                     console.log('installationData======',installationData)
//                     let data = {
//                         project_id: projectId || installationData[0]?.project_id || null,
//                         task_id: taskId || null,
//                         log_id: checkedItems?.join(',') || null,
//                         timelog_id: timeLogId || null,
//                         installation_id: installationIds || null,
//                         team: staffId,
//                         paid_at: now,
//                         amount: totalAmount,
//                         timestamp: moment().unix(),
//                         is_time_tracking: 1,
//                         added_by: userId,
//                         status:1,
//                         is_auto_pay:1
//                     };
//                     insertedstatus = await JobCost.addPayOut(data)
//                 }
//             }else{
//                 let data = {
//                     project_id: projectId || null,
//                     task_id: taskId || null,
//                     log_id: checkedItems?.join(',') || null,
//                     timelog_id: timeLogId || null,
//                     installation_id: installationIds || null,
//                     team: staffId,
//                     paid_at: now,
//                     amount: totalAmount,
//                     timestamp: moment().unix(),
//                     is_time_tracking: 1,
//                     added_by: userId,
//                     status:1,
//                     is_auto_pay:1
//                 };
//                 insertedstatus = await JobCost.addPayOut(data)
//             }
//             if (insertedstatus) {
//                 if(taskId){
//                 projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
//                 if(projectTaskDetails?.length > 0){
//                     projectTaskDetails = projectTaskDetails[0];
//                     // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
//                         stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
//                         console.log('stafftimelogs',stafftimelogs)
//                         if (stafftimelogs && stafftimelogs?.length > 0) {
//                             for (const subData of stafftimelogs) {
//                                 let subTaskArray = subData?.sub_task_id? subData?.sub_task_id?.split(","):[]
//                                 if(subTaskArray.length==0){
//                                     if (parseInt(subData.task_id) == taskId) {
//                                         const startMoment = moment.unix(subData.start_time);
//                                         let endMoment;
//                                         if (subData.end_time !== null) {
//                                             endMoment = moment.unix(subData.end_time);
//                                         } else {
//                                             endMoment = moment();
//                                         }
//                                         const duration = moment.duration(endMoment.diff(startMoment));
//                                         hours = duration.asHours();
//                                         subData['hours'] = hours
//                                         if (!isNaN(hours)) {
//                                             newhours += hours;
//                                         }
//                                     }
//                                 }else{

                                
//                                 for (const sub of subTaskArray) {
//                                     if (parseInt(subData.task_id) == taskId) {
//                                         const startMoment = moment.unix(subData.start_time);
//                                         let endMoment;
//                                         if (subData.end_time !== null) {
//                                             endMoment = moment.unix(subData.end_time);
//                                         } else {
//                                             endMoment = moment();
//                                         }
//                                         const duration = moment.duration(endMoment.diff(startMoment));
//                                         hours = duration.asHours();
//                                         subData['hours'] = hours
//                                         if (!isNaN(hours)) {
//                                             newhours += hours;
//                                         }
//                                     }
//                                 }
//                             }
//                             }
//                         }
                    
                       

//                         requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
//                         let hasHandledLabour10 = false;
//                         for(const item of requestServices){
//                             console.log('itemitemitemitemitem', item)
//                             console.log('projectTaskDetails', projectTaskDetails)
//                             if((projectTaskDetails.service_id == item.labour_cost_service_id && projectTaskDetails.customer_order_product_id == item.id) || item.id == selectedService){
//                                 if (item.labour_cost_service_id === 10) {
//                                     if (hasHandledLabour10) continue; // or continue if inside a loop
//                                     hasHandledLabour10 = true;
//                                     }
//                                 let payoutData = await JobCost.getPayOutByTaskId(projectId,taskId);
//                                 console.log('payoutData', payoutData)
//                                 if(payoutData && payoutData?.length > 0){
//                                     console.log('itemitemitemitemitem 2', item)
//                                     nnpayoutData = payoutData
//                                     let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
//                                     nntotalPayoutAmount = totalPayoutAmount
//                                     console.log('dfsfsfsfssfssfs', item?.jobcost_quantity , newhours)
//                                     let data = {
//                                         jobcost_quantity : Number(item?.jobcost_quantity) + newhours,
//                                         jobcost_unit_cost : staffHourlyRate || 0,
//                                         // jobcost_total_cost : parseFloat(Number(item?.jobcost_total_cost) + Number(totalPayoutAmount)).toFixed(2),
//                                         jobcost_total_cost : totalPayoutAmount,
//                                         taken : newhours >= item.qty ? 1 :0 
//                                     }
//                                     console.log('datadatadatadatadata', data)
//                                     let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
//                                     console.log('updateRequestServices 1',newhours,totalPayoutAmount)
//                                     console.log('updateRequestServices 2',updateRequestServices)
//                                     console.log('updateRequestServices 3',totalAmount)
//                                 }
//                             }
//                         }
//                     // }
//                 }}

//                 if(checkedInstallations && checkedInstallations?.length > 0){
//                     for (const instId of checkedInstallations){
//                         const installationData = await Installation.fetchApointmentById(instId);
//                         if(installationData && installationData?.length > 0){
//                             let requestId = installationData[0]?.request_id;
//                             // stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, newUserId, false, false, false, instId );
//                             stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, false, installationData[0]?.project_id, false, instId );
//                             if (stafftimelogs && stafftimelogs?.length > 0) {
//                                 for (const subData of stafftimelogs) {
//                                     // if (parseInt(subData.installation_id) == instId) {
//                                         const startMoment = moment.unix(subData.start_time);
//                                         let endMoment;
//                                         if (subData.end_time !== null) {
//                                             endMoment = moment.unix(subData.end_time);
//                                         } else {
//                                             endMoment = moment();
//                                         }
//                                         const duration = moment.duration(endMoment.diff(startMoment));
//                                         hours = duration.asHours();
//                                         subData['hours'] = hours
//                                         if (!isNaN(hours)) {
//                                             newhours1 += hours;
//                                         }
//                                     // }
//                                 }
//                             }
//                             let requestServices = await Request.getRequestServices(requestId);
//                             console.log('requestServices=========',requestServices);
//                             for(const item of requestServices){
//                                 console.log('labour_cost_service_id=========',item.labour_cost_service_id);
//                                 console.log('laborInstallId=========',laborInstallId);
//                                 if(item.labour_cost_service_id == laborInstallId){ // update the labor install service
//                                     const installationData = await Installation.fetchApointmentById(instId);
//                                     let payoutData = await JobCost.getPayOutByInstallationId(installationData[0]?.project_id,instId);
//                                     installationPayoutData = payoutData
//                                     console.log('payoutData=========',payoutData);
//                                     if(payoutData && payoutData?.length > 0){
//                                         let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
//                                         let data = {
//                                             jobcost_quantity : newhours1,
//                                             jobcost_unit_cost : staffHourlyRate || 0,
//                                             jobcost_total_cost : totalPayoutAmount,
//                                             taken : 1
//                                         }
//                                         let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
//                                     }
//                                 }
//                             }
//                         }
//                     }
//                 }
//                 if(checkedItems?.length > 0){
//                     for(const data of checkedItems){
//                         let updateData = {}
//                         updateData['status'] = 0
//                         await ProjectTask.updateLogStatus(updateData, data)
//                     }
//                 }
//                 notificationMsg = `New Pay Out has been added`;
//                 let notificationUrl = "staff-payout";
//                 const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);

//                 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);
//                     }
//                 }
//             }
//             let oldHours = newhours
//             let oldHours1 = newhours1
//             newhours = formatHoursToHHMMSS(newhours);
//             newhours1 = formatHoursToHHMMSS(newhours1);
//             reply.send({ status:1, message:"Task Timelog updated successfully",result:'update',newhours1,oldHours1,staffHourlyRate, nnpayoutData, nntotalPayoutAmount,
//                 notificationMsg:notificationMsg, projectTaskDetails,requestServices,stafftimelogs, newhours, oldHours, installationPayoutData })
        
//                 try {

//                     if(taskId){

                    
//                 const projectData = await ProjectTask.getTaskDetailsForqb(taskId)
//              console.log('elapsedTimeHourselapsedTimeHours--projectData',projectData)
//           const description = `Job "${projectData?.jobName}" progressed with clock-in on task "${projectData?.taskName}", resulting in a cost of $${totalAmount}.`;

//                   let amount =totalAmount
//                     await addJournalEntryToQuickBooks({
//                     amount,
//                     description
//                   });
//                 }
//                  } catch (error) {
//                      console.log("error",error)
//                  }
//             }else{
//             reply.send({status:0, message:"Failed to update timelog"})
//         }
//     }catch(error){
//         console.log("Update staff task timelog error : ",error);
//     }
// }

// newwwwwwwwwwwww
const updateStaffTaskTimelog = async (req, reply) => {
    try {
        const {
            checkedItems,
            taskId,
            projectId,
            userId,
            isDriver,
            person,
            minutesCurrent,
            hoursCurrent,
            memberClockins,
            project_category,
            now,
            request_id
        } = req.body;
        let notificationMsg = '';
        let newhoursTotal = 0;
        let nnpayoutData = null;
        let nntotalPayoutAmount = null;
        let requestServices = null;
        let projectTaskDetails = null;
        let stafftimelogs = null;
        let newhours = 0;
        let hours = 0;
        let installLabourService = null;
        const currentDate = Math.round(moment().valueOf() / 1000);
        let projects = await Project.getProjectById(projectId);
        
        // Get task details to check if it's manually added (fetch once before the loop)
        let taskDetails = null;
        let isTaskManuallyAdded = false;
        if (taskId) {
            taskDetails = await ProjectTask.getProjectTaskById(taskId);
            if (taskDetails?.length > 0) {
                isTaskManuallyAdded = taskDetails[0].is_manually_added === 1 || taskDetails[0].is_manually_added === "1";
                console.log('🔍 Task manually added check:', isTaskManuallyAdded);
            }
        }
        
        // Get installLabourService for Time & Material (category 12) projects
        // Note: We'll only use it if task is NOT manually added (checked in the loop)
        if(projects?.project_category == 12){
            installLabourService = await Request.getSingleRequestService10(projects?.request_id);
            console.log('requestService10', installLabourService)
        }
        console.log('📌 Received memberClockins:', memberClockins);
        console.log('📌projectsprojects', projects);
        const installId = person?.is_driver ? person?.installation_id : null

        for (const item of memberClockins) {
            const {
                staff_id,
                hour,
                service_id,
                subtask_id,
                task_id,
                start_time,
                end_time,
                hourly_rate,
                userId: staffUserId,
                staff_name,
                task_name,
                subtask_name
            } = item;

            const elapsedTimeSeconds = end_time - start_time;
            const elapsedTimeHours = elapsedTimeSeconds / 3600;
            const totalAmount = parseFloat((hourly_rate || 0) * elapsedTimeHours).toFixed(2);

            console.log(`⏱️ Processing staff ID ${staff_id} - Hours: ${hour}, Amount: ${totalAmount}`);

            // Use taskId from request body if task_id is not provided in memberClockins item
            const taskIdToUse = task_id || taskId;
            
            let productTaskServiceId = null;
            
            // Only fetch services from task if taskIdToUse is available and task is NOT manually added
            // (we already know if task is manually added from the pre-fetched taskDetails)
            if (taskIdToUse && !isTaskManuallyAdded) {
                const getServicesFromTask = await ProjectTask.getServicesFromProductTask(taskIdToUse);
                console.log('getServicesFromTask+++', getServicesFromTask)
                productTaskServiceId = getServicesFromTask?.requestServices[0]?.id || getServicesFromTask?.projectTask?.customer_order_product_id;
            }
            
            // For manually added tasks, service_id should be null
            // Otherwise, use the provided service_id or fallback to installLabourService or productTaskServiceId
            let finalServiceId = null;
            if (isTaskManuallyAdded) {
                // For manually added tasks, always set service_id to null
                finalServiceId = null;
                console.log('🔧 Task is manually added, setting service_id to null');
            } else {
                // For non-manually added tasks, use existing logic
                // Use service_id from memberClockins first, then fallback to other options
                finalServiceId = service_id || installLabourService?.id || productTaskServiceId || (person?.is_driver ? person?.service_id : null);
            }
            console.log('finalServiceIdfinalServiceId', finalServiceId,service_id)
            
            const timeLogData = {
                job_id: projectId,
                task_id: taskId,
                sub_task_id: subtask_id,
                user_id: staffUserId,
                start_time,
                end_time,
                status: 1,
                service_id: finalServiceId,
                installation_id: installId
            };
            const timeLogId = await ProjectTask.addStaffTaskTimelog(timeLogData);
            console.log('🧾 Created timelog ID:', timeLogId);

            const payoutData = {
                project_id: projectId,
                task_id: taskId,
                log_id: checkedItems?.join(',') || subtask_id ||null,
                timelog_id: timeLogId,
                installation_id: null,
                team: null,
                paid_at: end_time,
                amount: totalAmount,
                timestamp: moment().unix(),
                is_time_tracking: 1,
                added_by: userId,
                service_id: finalServiceId,
                status: 1,
                is_auto_pay: 1,
                installation_id: installId
            };
            await JobCost.addPayOut(payoutData);
            newhoursTotal += parseFloat(hour);

            // ---- JobCost log (per timelog) ----
            const staffName = staff_name || person?.staff_name || `${person?.staff_first_name || ''} ${person?.staff_last_name || ''}`.trim();
            
            // Calculate hours and minutes from hour value
            const totalMinutes = Math.round(hour * 60);
            const hh = Math.floor(totalMinutes / 60);
            const mm = totalMinutes % 60;

            const finalTaskName = task_name || (person?.installation ? 'labour install' : (person?.task_name || projectTaskDetails?.task_name || 'N/A'));
            const finalSubtaskName = subtask_name || (person?.installation ? 'labour install' : (person?.subtask_name || 'N/A'));

            let logMessage = '';
            if ((project_category == 12 && !isTaskManuallyAdded) || person?.installation ) {
                logMessage = `'${staffName}' worked on labor install.` 
            } else {
                logMessage = `'${staffName}' worked ${hh}h ${mm}m on task '${finalTaskName}' (subtask: '${finalSubtaskName}').`;
            }
            await JobCost.addJobCostLog({
                message: sanitizeLog(logMessage),
                user_id: userId,
                timestamp: moment().unix(),
                status: 1,
                project_id: projectId
            });

            let requestActivity = {}
            requestActivity['request_id'] = request_id || null;
            requestActivity['activity'] = sanitizeLog(logMessage);
            requestActivity['added_by'] = userId;
            requestActivity['timestamp'] = currentDate;
            requestActivity['status'] = 1;
            let reqActivityId = await RequestActivity.addRequestUpdate(requestActivity)
            console.log('reqActivityId',reqActivityId)
         try {
         if(projectId){

        //    const projectData = await ProjectTask.getTaskDetailsForqb(taskId)
           const projectData = await ProjectTask.getJobDetailsForqb(projectId)
           console.log('addJournalEntryToQuickBooks projectData',projectData)
        //    const description = `Job "${projectData?.jobName}" progressed with clock-in on task "${projectData?.taskName}", resulting in a cost of $${totalAmount}.`;
           const description = `Job "${projectData?.jobName}" progressed with clock-in , resulting in a cost of $${totalAmount}.`;

                  let amount =totalAmount
                  if(projectData?.syncWithQuickbooks == 1){
                    await addJournalEntryToQuickBooks({
                    amount,
                    description,
                    projectTypeQuickBookId:projectData?.projectTypeQuickBookId,
                    docNumber:projectData?.doc_number,
                    requestId:projectData?.requestId
                  });
                }
                }
            } catch (error) {
               console.log("error",error)
        }
        }

        if (taskId) {
            projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
            console.log('projectTaskDetailsprojectTaskDetails 1', projectTaskDetails)
        }else if(projectId){
            projectTaskDetails = await ProjectTask.getProjectDataById(projectId);
            console.log('projectTaskDetailsprojectTaskDetails 2', projectTaskDetails)
        }
        if (projectTaskDetails?.length > 0 ) {
            projectTaskDetails = projectTaskDetails[0]; 
            console.log('projectTaskDetails', projectTaskDetails)
            // stafftimelogs = await ProjectTask.fetchStaffTaskTimelog(false, false, taskId, false, false);
            stafftimelogs = await ProjectTask.fetchStaffTimelogsByProjectId(null, null, projectTaskDetails.project_id);;
            console.log('stafftimelogs--', stafftimelogs)
            requestServices = await Request.getRequestServices(projectTaskDetails.request_id,false,false,false,projectTaskDetails?.project_category);
            let hasHandledLabour10 = false;

            // for (const item of requestServices) {
            //   console.log('🔧 Processing RequestService item:', item);
            //   const matchedService = memberClockins.find(mc => mc.service_id === item.id);
            //   if ((projectTaskDetails.service_id === item.labour_cost_service_id && projectTaskDetails.customer_order_product_id === item.id) || matchedService) {
            //     if (item.labour_cost_service_id === 10 && hasHandledLabour10) continue;
            //     hasHandledLabour10 = true;

            //     const payoutData = await JobCost.getPayOutByTaskId(projectId, taskId);
            //     console.log('📦 Total PayoutData:', payoutData);

            //     if (payoutData?.length > 0) {
            //       nnpayoutData = payoutData;
            //       const totalPayoutAmount = payoutData.reduce((total, p) => total + (p.amount || 0), 0);
            //       nntotalPayoutAmount = totalPayoutAmount;
            //     console.log('📦 updated total == totalPayoutAmount', totalPayoutAmount,newhours,item?.hourly_rate);

            //       const data = {
            //         jobcost_quantity: Number(item?.jobcost_quantity) + newhours,
            //         jobcost_unit_cost: item?.hourly_rate || 0,
            //         jobcost_total_cost: totalPayoutAmount,
            //         taken: newhours >= item.qty ? 1 : 0
            //       };
            //     console.log('📦 updated total == data', data);


            //       const updateResult = await Request.updateRequestServices(data, item.id, item.request_id);
            //       console.log('✅ Updated RequestService:', updateResult);
            //     }
            //   }
            // }
            for (const item of requestServices) {
                console.log('🔧 Processing RequestService item:', item);
                // Only update once for labour install service (ID = 10)
                if (item.labour_cost_service_id === 10 && hasHandledLabour10) continue;
                if (item.labour_cost_service_id === 10) hasHandledLabour10 = true;
                console.log('stafftimelogssssssssssssssss', stafftimelogs)
                // Get timelogs matching both taskId and service_id === requestService.id

                if (!stafftimelogs) {
                    console.log(`❌ No timelogs found`);
                    continue;
                }

                const matchedTimelogs = stafftimelogs.filter(
                    (log) => parseInt(log.service_id) === item.id
                );

                if (matchedTimelogs.length === 0) {
                    console.log(`❌ No matching timelogs found for RequestService ID ${item.id}`);
                    continue;
                }

                // Sum hours
                let totalHours = 0;
                for (const log of matchedTimelogs) {
                    const startMoment = moment.unix(log.start_time);
                    const endMoment = log.end_time !== null ? moment.unix(log.end_time) : moment();
                    const duration = moment.duration(endMoment.diff(startMoment));
                    const logHours = duration.asHours();
                    if (!isNaN(logHours)) totalHours += logHours;
                    console.log(`⏱️ Timelog ${log.id} => ${logHours} hours`, 'totallll', totalHours);
                }

                // Filter payouts related to this specific service
                const allPayouts = await JobCost.getPayOutByServiceId(projectId, item.id);
                console.log('allPayoutsallPayouts', allPayouts)
                //   const relevantTimelogIds = matchedTimelogs.map(log => log.id);
                //   const payoutData = allPayouts.filter(p => relevantTimelogIds.includes(p.timelog_id));
                const payoutData = allPayouts;
                console.log('payoutDatapayoutData', payoutData)

                if (payoutData?.length > 0) {
                    nnpayoutData = payoutData;
                    const totalPayoutAmount = payoutData.reduce((total, p) => total + (p.amount || 0), 0);
                    nntotalPayoutAmount = totalPayoutAmount;

                    console.log('totalHourstotalHours', totalHours, item?.jobcost_quantity)

                    const data = {
                        jobcost_quantity: totalHours,
                        jobcost_unit_cost: item?.hourly_rate || 0,
                        jobcost_total_cost: totalPayoutAmount,
                        taken: 1 //totalHours >= item.qty ? 1 : 0
                    };
                    if(projectTaskDetails?.project_category == 12 && item?.labour_cost_service_id === 10){
                        console.log('11111111111111')
                        let installHours = totalHours?.toFixed(2)
                        data.qty = installHours;
                        data.total_cost = ((installHours || 0) * item.unit_cost);
                        // data.unit_cost = staffHourlyRate || 0
                    }

                    console.log(`✅ Matched service_id=${item.id}, totalHours=${totalHours}, totalPayoutAmount=${totalPayoutAmount}`);
                    console.log('📦 Final jobcost update payload:', data);

                    const updateResult = await Request.updateRequestServices(data, item.id, item.request_id);
                    console.log('✅ Updated RequestService:', updateResult);
                } else {
                    console.log(`⚠️ No payout data found for service_id=${item.id}`);
                }
            }
            await new Promise(resolve => setTimeout(resolve, 100));
            const takenItems = await Request.getAllRecipeRequestServices(projectTaskDetails?.request_id);;
            console.log('takenItems', takenItems)

            if (takenItems?.some(item => item.taken === 1)) {
            const updateAllTaken = await Request.updateAllRecipesTakenByRequestId(projectTaskDetails?.request_id);
            console.log('✅ All recipe services marked as taken for request_id:', projectTaskDetails.request_id);
            }
        }

        if (checkedItems?.length > 0) {
            for (const data of checkedItems) {
                await ProjectTask.updateLogStatus({ status: 0 }, data);
                console.log('✅ Updated Log Status to 0 for:', data);
            }
        }

        // === Notification ===
        notificationMsg = `New Pay Out has been added`;
        let notificationUrl = "staff-payout";

        await Admin.incrementField(userId, "noti_count", 1);
        await Admin.addNotification({
            user_id: userId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId
        });

        const adminIds = await Admin.getAllAdminIds();
        for (const adminId of adminIds) {
            if (adminId != userId) {
                await Admin.incrementField(adminId, "noti_count", 1);
                await Admin.addNotification({
                    user_id: adminId,
                    url: notificationUrl,
                    timestamp: currentDate,
                    message: notificationMsg,
                    status: 1,
                    from_id: userId
                });
            }
        }

        let oldHours = newhours;
        newhours = formatHoursToHHMMSS(newhours);
        // Get the username
        reply.send({
            status: 1,
            message: "Task Timelog updated successfully",
            result: 'update',
            newhours,
            oldHours,
            notificationMsg,
            nnpayoutData,
            nntotalPayoutAmount,
            projectTaskDetails,
            requestServices,
            stafftimelogs
        });
    } catch (error) {
        console.log("❌ Update staff task timelog error:", error);
        reply.send({ status: 0, message: "Failed to update timelog" });
    }
};

const updateStaffTaskTimelogDriverAndInstaller = async (req, reply) => {
  try {
    const {
      checkedItems,
      taskId,
      projectId,
      checkedInstallations,
      driverUserID,
      userId,
      isDriver,
    //   timeLogId,
      now,
      startTime,
      staffId,
      staffHourlyRate
    } = req.body;

          console.log("clockin function 4 updateStaffTaskTimelogDriverAndInstaller",req.body)

    let notificationMsg = '';
    let projectTaskDetails = '';
    let requestServices = '';
    let stafftimelogs = '';
    let newhours = 0;
    let newhours1 = 0;
    let hours = 0;
    let laborInstallId = 10;
    let installationIds = checkedInstallations?.join(', ') || null;
    let installationPayoutData = null;
    let nnpayoutData = null;
    let nntotalPayoutAmount = null;
    let insertedstatus = false;

    let currentDate = Math.round(moment().valueOf() / 1000);
    const elapsedTimeSeconds = now - startTime;
    const elapsedTimeHours = elapsedTimeSeconds / 3600;

    const installationData = await Installation.fetchInstallationDataById(checkedInstallations[0]);
    console.log('installationData',installationData)
    const participants = [];

    if (installationData.driverData?.length > 0) {
      for (const driver of installationData.driverData) {
        participants.push({
          user_id: driver.user_id,
          role: 'driver',
          hourly_rate: driver.hourly_rate || staffHourlyRate || 0,
          timelog_id:driver.timelog_id
        });
      }
    }

    if (installationData.teamData?.length > 0) {
      const installer = installationData.teamData[0];
      const alreadyAdded = participants.some(p => p.user_id === installer.user_id);
      if (!alreadyAdded) {
        participants.push({
          user_id: installer.user_id,
          role: 'installer',
          hourly_rate: installer.hourly_rate || staffHourlyRate || 0,
          timelog_id:installer.timelog_id

        });
      }
    }

    for (const person of participants) {
      const payoutAmount = person.hourly_rate * elapsedTimeHours;
      const updateData = { end_time: now || currentDate };
  let timeLogId = person.timelog_id;
      const updated = await ProjectTask.updateStaffTaskTimelog(
        updateData,
        taskId,
        projectId,
        checkedInstallations,
        person.user_id,
        timeLogId 
      );
      console.log('updatedupdatedupdatedupdated',updated,person)

      if (updated) {
        for (const instId of checkedInstallations) {
          const instData = await Installation.fetchApointmentById(instId);
          const payoutData = {
            project_id: projectId || instData[0]?.project_id || null,
            task_id: taskId || null,
            log_id: checkedItems?.join(',') || null,
            timelog_id: timeLogId || null,
            installation_id: installationIds,
            team: person.user_id,
            paid_at: now,
            amount: payoutAmount,
            timestamp: currentDate,
            is_time_tracking: 1,
            added_by: userId,
            status: 1,
            is_auto_pay: 1
          };
          const payoutResult = await JobCost.addPayOut(payoutData);
          if (payoutResult) insertedstatus = true;
        }
      }
    }

    if (insertedstatus) {
      if (taskId) {
        projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
        if (projectTaskDetails?.length > 0) {
          projectTaskDetails = projectTaskDetails[0];
          stafftimelogs = await ProjectTask.fetchStaffTaskTimelog(false, false, taskId, false, false);
          if (stafftimelogs?.length > 0) {
            for (const subData of stafftimelogs) {
              const subTaskArray = subData?.sub_task_id ? subData?.sub_task_id.split(",") : [];
              const startMoment = moment.unix(subData.start_time);
              const endMoment = subData.end_time ? moment.unix(subData.end_time) : moment();
              const duration = moment.duration(endMoment.diff(startMoment));
              hours = duration.asHours();
              subData['hours'] = hours;
              if (!isNaN(hours)) newhours += hours;
            }
          }

          requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
          for (const item of requestServices) {
            if (projectTaskDetails.service_id == item.labour_cost_service_id) {
              const payoutData = await JobCost.getPayOutByTaskId(projectId, taskId);
              if (payoutData?.length > 0) {
                nnpayoutData = payoutData;
                const totalPayoutAmount = payoutData.reduce((total, item) => total + (item.amount || 0), 0);
                nntotalPayoutAmount = totalPayoutAmount;

                await Request.updateRequestServices({
                  jobcost_quantity: newhours,
                  jobcost_unit_cost: staffHourlyRate || 0,
                  jobcost_total_cost: totalPayoutAmount,
                  taken: newhours >= item.qty ? 1 : 0
                }, item.id, item.request_id);
              }
            }
          }
        }
      }

      for (const instId of checkedInstallations) {
        const instData = await Installation.fetchApointmentById(instId);
        const requestId = instData[0]?.request_id;

        stafftimelogs = await ProjectTask.fetchStaffTaskTimelog(false, false, false, instData[0]?.project_id, false, instId);
       console.log('stafftimelogsstafftimelogs',stafftimelogs)
        if (stafftimelogs?.length > 0) {
          for (const subData of stafftimelogs) {
            const startMoment = moment.unix(subData.start_time);
            const endMoment = subData.end_time ? moment.unix(subData.end_time) : moment();
            const duration = moment.duration(endMoment.diff(startMoment));
            hours = duration.asHours();
            subData['hours'] = hours;
            if (!isNaN(hours)) newhours1 += hours;
          }
        }

        const reqServices = await Request.getRequestServices(requestId);
        for (const item of reqServices) {
          if (item.labour_cost_service_id == laborInstallId) {
            const payoutData = await JobCost.getPayOutByInstallationId(instData[0]?.project_id, instId);
            if (payoutData?.length > 0) {
              installationPayoutData = payoutData;
              const totalPayoutAmount = payoutData.reduce((total, item) => total + (item.amount || 0), 0);
              await Request.updateRequestServices({
                jobcost_quantity: newhours1,
                jobcost_unit_cost: staffHourlyRate || 0,
                jobcost_total_cost: totalPayoutAmount,
                taken: 1
              }, item.id, item.request_id);
              console.log('datatattt',newhours1,totalPayoutAmount)
            }
          }
        }
      }

      if (checkedItems?.length > 0) {
        for (const logId of checkedItems) {
          await ProjectTask.updateLogStatus({ status: 0 }, logId);
        }
      }

      notificationMsg = `New Pay Out has been added`;
      const notificationUrl = "staff-payout";
      await Admin.incrementField(userId, "noti_count", 1);

      await Admin.addNotification({
        user_id: userId,
        url: notificationUrl,
        timestamp: currentDate,
        message: notificationMsg,
        status: 1,
        from_id: userId
      });

      const adminIds = await Admin.getAllAdminIds();
      for (const adminId of adminIds) {
        if (adminId != userId) {
          await Admin.incrementField(adminId, "noti_count", 1);
          await Admin.addNotification({
            user_id: adminId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId
          });
        }
      }

      let oldHours = newhours;
      let oldHours1 = newhours1;
      newhours = formatHoursToHHMMSS(newhours);
      newhours1 = formatHoursToHHMMSS(newhours1);

      reply.send({
        status: 1,
        message: "Task Timelog updated successfully",
        result: 'update',
        newhours1,
        oldHours1,
        staffHourlyRate,
        nnpayoutData,
        nntotalPayoutAmount,
        notificationMsg,
        projectTaskDetails,
        requestServices,
        stafftimelogs,
        newhours,
        oldHours,
        installationPayoutData
      });
    } else {
      reply.send({ status: 0, message: "Failed to update timelog" });
    }
  } catch (error) {
    console.log("Update staff task timelog error : ", error);
    reply.send({ status: 0, message: "Error updating timelog", error });
  }
};

const updateInstallerTaskTimelog = async (req, reply) => {
    console.log("reqbody clock out",req.body);
    
    try{
        const {checkedItems, taskId, projectId, checkedInstallations, driverUserID,
             userId, isDriver, timeLogId, now, startTime, staffId, staffHourlyRate,userType,
            createInstallLabour,staffUserId,hasAcceptedRoutesPermission} = req.body
        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let newhours1 = 0;
        let hours = 0;
        let laborInstallId = 10;
        let installationIds = null;
        let installationPayoutData = null
        let nnpayoutData = null;
        let nntotalPayoutAmount = null;
          console.log("clockin function 3 updateStaffTaskTimelog")
        if(checkedInstallations && checkedInstallations?.length > 0){
            installationIds = checkedInstallations?.join(', ')
        }
        let currentDate = Math.round(moment().valueOf() / 1000);
        const elapsedTimeSeconds = now - startTime;
        const elapsedTimeHours = elapsedTimeSeconds / 3600;
        const totalAmount = parseFloat((staffHourlyRate || 0) * elapsedTimeHours).toFixed(2);
        console.log('elapsedTimeHourselapsedTimeHours--startTime',startTime)
        console.log('elapsedTimeHourselapsedTimeHours--now',now)
        console.log('elapsedTimeHourselapsedTimeHours--elapsedTimeHours',elapsedTimeHours)
        console.log('elapsedTimeHourselapsedTimeHours--totalAmount',totalAmount)
        console.log('elapsedTimeHourselapsedTimeHours--checkedItems',checkedItems)
        
      

  
     

        let staffTaskTimelogData = {}
        staffTaskTimelogData.end_time = now ? now : currentDate
        
        
           
                for(const instId of checkedInstallations){
                    const installationData = await Installation.fetchApointmentById(instId);
                    console.log('installationData======',installationData)
                    let teamIds = [];
                    if(hasAcceptedRoutesPermission){
                        teamIds = [...new Set([userId, ...(installationData[0]?.team_id || '').split(',').map(id => id.trim()).filter(Boolean)])];
                    }else{
                        teamIds = [...new Set((installationData[0]?.team_id || '').split(',').map(id => id.trim()).filter(Boolean))];
                    }
                    if(staffUserId){
                        teamIds = [staffUserId];
                    }
                    console.log('teamIdsteamIds', teamIds)
                    const newUserId = isDriver ? driverUserID : userId

                    for (const teamUserId of teamIds) {
                   const updateResult = await ProjectTask.updateInstallerTaskTimelog(staffTaskTimelogData, taskId, projectId, checkedInstallations, teamUserId, timeLogId);
                        console.log('updateResult====',updateResult)
                    let userHourlyRate = await Driver.getDriverHourlyRate(teamUserId)
        
        const eachInstallerTotalAmount = parseFloat((userHourlyRate || 20) * elapsedTimeHours).toFixed(2);
                    const getSingleRequestService10 = await Request.getSingleRequestService10(installationData[0]?.request_id)
                    console.log('getSingleRequestService10',getSingleRequestService10)
                      
                    let data = {
                        project_id: projectId || installationData[0]?.project_id || null,
                        task_id: taskId || null,
                        log_id: checkedItems?.join(',') || null,
                        timelog_id: timeLogId || null,
                        installation_id: installationIds || null,
                        team: staffId,
                        paid_at: now,
                        amount: eachInstallerTotalAmount,
                        timestamp: moment().unix(),
                        is_time_tracking: 1,
                        added_by: userId,
                        status:1,
                        is_auto_pay:1,
                        service_id: getSingleRequestService10?.id || null
                    };
                    insertedstatus = await JobCost.addPayOut(data)
                }
            }
            
         
            if (insertedstatus) {
                if(taskId){
                projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
                if(projectTaskDetails?.length > 0){
                    projectTaskDetails = projectTaskDetails[0];
                    // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
                        stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
                        console.log('stafftimelogs',stafftimelogs)
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray = subData?.sub_task_id? subData?.sub_task_id?.split(","):[]
                                if(subTaskArray.length==0){
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        hours = duration.asHours();
                                        subData['hours'] = hours
                                        if (!isNaN(hours)) {
                                            newhours += hours;
                                        }
                                    }
                                }else{

                                
                                for (const sub of subTaskArray) {
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        hours = duration.asHours();
                                        subData['hours'] = hours
                                        if (!isNaN(hours)) {
                                            newhours += hours;
                                        }
                                    }
                                }
                            }
                            }
                        }
                    
                            // const getRequest = await Request.getRequestById(projectTaskDetails?.request_id, userId, userType);
                            // const originalRequest = getRequest[0];
                            // console.log('originalRequest', originalRequest)
                       
                        requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
                        let hasHandledLabour10 = false;
                        for(const item of requestServices){
                            if(projectTaskDetails.service_id == item.labour_cost_service_id){
                                if (item.labour_cost_service_id === 10) {
                                    if (hasHandledLabour10) continue;
                                    hasHandledLabour10 = true;
                                }
                                let payoutData = await JobCost.getPayOutByTaskId(projectId,taskId);
                                console.log('payoutDatapayoutData', payoutData,newhours)
                                if(payoutData && payoutData?.length > 0){
                                    nnpayoutData = payoutData
                                    let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
                                    nntotalPayoutAmount = totalPayoutAmount
                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_unit_cost : staffHourlyRate || 0,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : newhours >= item.qty ? 1 :0 
                                    }
                                    // if(originalRequest?.project_category == 12){
                                    //     data.qty = newhours;
                                    //     data.total_cost = totalPayoutAmount;
                                    //     // data.unit_cost = staffHourlyRate || 0
                                    // }
                                    let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
                                    console.log('updateRequestServices 1',newhours,totalPayoutAmount)
                                    console.log('updateRequestServices 2',updateRequestServices)
                                    console.log('updateRequestServices 3',totalAmount)
                                }
                            }
                        }
                    // }
                }}

                if(checkedInstallations && checkedInstallations?.length > 0){
                    for (const instId of checkedInstallations){
                        const installationData = await Installation.fetchApointmentById(instId);
                        if(installationData && installationData?.length > 0){
                            let requestId = installationData[0]?.request_id;
                            let isTimeandMaterial = installationData[0]?.project_category == 12 ? true : false;
                            // if(isTimeandMaterial){
                            //     stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, false, installationData[0]?.project_id, false, null, true );
                            // }else{
                                stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, false, installationData[0]?.project_id, false, instId );
                            // }
                            console.log('stafftimelogs=========1',stafftimelogs)
                            if (stafftimelogs && stafftimelogs?.length > 0) {
                                for (const subData of stafftimelogs) {
                                    // if (parseInt(subData.installation_id) == instId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        hours = duration.asHours();
                                        subData['hours'] = hours
                                        if (!isNaN(hours)) {
                                            newhours1 += hours;
                                        }
                                    // }
                                }
                            }
                           
                            let requestServices = await Request.getRequestServices(requestId);
                            console.log('requestServices=========1',requestServices);
                            let hasHandledLabour10 = false;
                            for(const item of requestServices){
                                console.log('labour_cost_service_data=========',item);
                                console.log('labour_cost_service_id=========',item.labour_cost_service_id);
                                console.log('laborInstallId=========',laborInstallId);
                                if(item.labour_cost_service_id == laborInstallId){ // update the labor install service
                                    if (item.labour_cost_service_id === 10) {
                                        if (hasHandledLabour10) continue;
                                        hasHandledLabour10 = true;
                                    }
                                    const installationData = await Installation.fetchApointmentById(instId);
                                    let payoutData = [];
                                    // if(isTimeandMaterial){
                                    //     payoutData = await JobCost.getPayOutByInstallationId(installationData[0]?.project_id);
                                    // }else{
                                        payoutData = await JobCost.getPayOutByInstallationId(installationData[0]?.project_id,instId);
                                    // }
                                    
                                    installationPayoutData = payoutData
                                    console.log('payoutData=========',payoutData);
                                    if(payoutData && payoutData?.length > 0){
                                        let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
                                        console.log('updateddddd hoursss',item.jobcost_quantity, newhours1)
                                        let data = {
                                            jobcost_quantity : newhours1,
                                            jobcost_unit_cost : staffHourlyRate || 0,
                                            jobcost_total_cost : totalPayoutAmount,
                                            taken : 1
                                        }
                                        if(installationData[0]?.project_category == 12){
                                            let installHours = newhours1?.toFixed(2)
                                            data.qty = installHours;
                                            data.total_cost = ((installHours || 0) * item.unit_cost);
                                            // data.unit_cost = staffHourlyRate || 0
                                        }
                                        console.log('updateddddd timelog', data)
                                        let updateRequestServices = await Request.updateRequestServices(data,item.id,requestId)
                                    if(updateRequestServices){
                                        const getPayout = await JobCost.getPayOutByInstallation(instId)
                                        console.log('getPayout', getPayout)
                                        if(getPayout){
                                            const updatePayout = await JobCost.updatePayOutByInstallation(instId,item?.id)
                                            console.log('updatePayoutttt', updatePayout)
                                            const updateTimelog = await JobCost.updateStaffTaskTimelogByInstallation(instId,item?.id)
                                        
                                        }
                                    }
                                    }
                                }
                            }
                        }
                    }
                }
                if(checkedItems?.length > 0){
                    for(const data of checkedItems){
                        let updateData = {}
                        updateData['status'] = 0
                        await ProjectTask.updateLogStatus(updateData, data)
                    }
                }
                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);

                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);
                    }
                }
            }
            let oldHours = newhours
            let oldHours1 = newhours1
            newhours = formatHoursToHHMMSS(newhours);
            newhours1 = formatHoursToHHMMSS(newhours1);
            reply.send({ status:1, message:"Task Timelog updated successfully",result:'update',newhours1,oldHours1,staffHourlyRate, nnpayoutData, nntotalPayoutAmount,
                notificationMsg:notificationMsg, projectTaskDetails,requestServices,stafftimelogs, newhours, oldHours, installationPayoutData })
        
                try {

                    // if(taskId){

                    
                // const projectData = await ProjectTask.getTaskDetailsForqb(taskId)
                const projectData = await ProjectTask.getJobDetailsFromInstallationIdForqb(checkedInstallations[0]) 
             console.log('elapsedTimeHourselapsedTimeHours--projectData',projectData)
          const description = `Job "${projectData?.jobName}" progressed with clock-in , resulting in a cost of $${totalAmount}.`;

                  let amount =totalAmount
                  if(projectData?.syncWithQuickbooks == 1){
                    await addJournalEntryToQuickBooks({
                    amount,
                    description,
                    projectTypeQuickBookId:projectData?.projectTypeQuickBookId,
                    docNumber:projectData?.doc_number,
                    requestId:projectData?.requestId
                  });
                  }
                // }
                 } catch (error) {
                     console.log("error",error)
                 }
            
          
    }catch(error){
        console.log("Update staff task timelog error : ",error);
    }
}



const fetchStaffTaskTimelog = async (req, reply) => {
    try{
        const {id,userId,projectId,logIds,taskId} = req.body;
        const logIdArray = logIds?.split(',')
        const result = await ProjectTask.fetchStaffTaskTimelog(id,userId,taskId,projectId,logIdArray)
        if(result){
            reply.send({status:1, message:"Timelog fetched successfully",result:result})
        }else{
            reply.send({status:0, message:"No timelogs found"})
        }
    }catch(error){
        console.log("Error fetching staff task timelog : ",error);
        reply.send({status:500, message:"Error fetching timelog",error:error})
    }
}

const fetchAllStaffTaskTimelog = async (req, reply) => {
    try{
        const { search = '', page = 1, limit = 10, orderBy = 'id', order = 'desc', source = 'regular', staffFilter = [], projectFilter = [], taskFilter = [], dateFrom = null, dateTo = null } = req.body;

        const result = await ProjectTask.fetchAllStaffTaskTimelog(search, page, limit, orderBy, order, source, staffFilter, projectFilter, taskFilter, dateFrom, dateTo);
        
        // Process subtask names for the returned data
        if(result?.data && result.data.length > 0){
            for(const data of result.data){
            if(data?.sub_task_id){
                const subTaskIdArray = data.sub_task_id.split(',')
                const resArray = []
                for(const subData of subTaskIdArray){
                        let subTaskName;
                        if (source === 'design') {
                            subTaskName = await ProjectTask.fetchDesignOrderSubTaskName(parseInt(subData));
                        } else {
                            subTaskName = await ProjectTask.fetchSubTaskName(parseInt(subData));
                        }
                resArray.push(subTaskName[0]?.sub_task_name)
                }
                data.sub_task_name = resArray.join(', ');
                } else if (data?.installation_id_val) {
                    // For installations, there are no subtasks
                    data.sub_task_name = '';
            } else {
                data.sub_task_name = data?.sub_task_name || '';
            }
        }
        }
        
        if(result){
            reply.send({
                status:1, 
                message:"All Timelogs fetched successfully",
                result: result.data || [],
                totalCount: result.totalCount || 0,
                page: result.page || page,
                limit: result.limit || limit
            })
        }else{
            reply.send({
                status:0, 
                message:"No timelogs found",
                result: [],
                totalCount: 0,
                page: page,
                limit: limit
            })
        }
    }catch(error){
        console.log("Error fetching staff task timelog : ",error);
        reply.send({
            status:500, 
            message:"Error fetching timelog",
            error:error,
            result: [],
            totalCount: 0
        })
    }
}

const fetchClockedInStaffTaskTimelog = async (req, reply) => {
    try{
        const {userId, projectId, taskId, isDriver, instIds,hasAcceptedRoutesPermission} = req.body;
        const result = await ProjectTask.fetchClockedInStaffTaskTimelog(userId, projectId, taskId, isDriver, instIds,hasAcceptedRoutesPermission);
        if(result){
            reply.send({status:1, message:"Timelog fetched successfully",result:result})
        }else{
            reply.send({status:0, message:"No open timelog found"})
        }
    }catch(error){
        console.log("Error fetching staff task timelog : ",error);
        reply.send({status:500, message:"Error fetching timelog",error:error})
    }
}



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

async function downloadFirebaseFile(firebaseUrl, savePath) {
    try {
        const response = await axios.get(firebaseUrl, { responseType: "arraybuffer" });
        fs.writeFileSync(savePath, response.data);
        console.log("✅ File downloaded successfully:", savePath);
        return savePath;
    } catch (error) {
        console.error("❌ Error downloading file:", error.message);
        return null;
    }
}

async function sendReceiptEmail(firebaseUrl) {
    const filePath = path.join(__dirname, "receipt.png"); // Save file in the current directory

    // ✅ Step 1: Download the file from Firebase
    const downloadedFilePath = await downloadFirebaseFile(firebaseUrl, filePath);
    if (!downloadedFilePath) {
        console.error("❌ Failed to download the file, email not sent.");
        return;
    }

 

    const mailOptions = {
        from: '"SignWise Solutions" <noreply@signwisesolutions.com>',
        // to: "sandbox_company_us_1_9394+expenses@assist.intuit.com",
        to: qbReceptFromEmailAcc,
        subject: "A New Receipt",
        text: "A new receipt has been received",
        attachments: [
            {
                filename: "receipt.png",
                path: downloadedFilePath,
                contentType: "image/png",
            },
        ],
    };

    // ✅ Step 3: Send the Email
    if(SEND_EMAIL){
    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
            console.error("❌ Error sending email:", error);
        } else {
            console.log("✅ Email sent successfully:", info.response);
        }

        // 🧹 Step 4: Cleanup - Remove the file after sending
        fs.unlinkSync(downloadedFilePath);
    });
}
}



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

const addManualStaffTaskTimelog = async (req, reply) => {
    try{
        const {taskId, service_id, projectId,userId, endTime, startTime, staffId, staff, staffHourlyRate, hours, totalAmount,cover,description} = req.body
        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let totalHours = 0;
        let currentDate = Math.round(moment().valueOf() / 1000);
        // const elapsedTimeSeconds = endTime - startTime;
        // const elapsedTimeHours = elapsedTimeSeconds / 3600;
        // const totalAmount = (staffHourlyRate || 0) * elapsedTimeHours  


        
     

        let data = {}
        data.job_id = projectId
        data.task_id = taskId
        data.service_id = service_id || null
        data.sub_task_id = null
        data.user_id = staffId
        data.start_time = startTime
        data.end_time = endTime || startTime
        data.status = 1
        data.noSubTask = 0
        const addStaffTaskTimelog = await ProjectTask.addStaffTaskTimelog(data);
        if(addStaffTaskTimelog){
            let data = {
                project_id: projectId,
                task_id: taskId,
                service_id: service_id || null,
                log_id: null,
                team: staff.id,
                paid_at: startTime,
                end_date: endTime,
                hours: hours,
                amount: totalAmount,
                timestamp: moment().unix(),
                is_time_tracking: 0,
                added_by: userId,
                status:userId == 1?1 : 5,
                is_auto_pay:0,
                cover:cover,
                description:description
            };
            const insertedstatus = await JobCost.addPayOut(data)
            if(insertedstatus){

                try {
                    if(userId == 1 && cover){
                        await sendReceiptEmail(cover);
                    }else{
                        console.log("need approval")
                    }
                    
                        } catch (error) {
                            console.log('error',error)
                        }
        

                // try {
                //  const response = uploadReceiptToQuickBooks(insertedstatus,cover,"sandbox")
                // } catch (error) {
                //     console.log('error',error)
                // }
                projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
                if(projectTaskDetails?.length > 0){
                    projectTaskDetails = projectTaskDetails[0];
                    // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
                        // stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, staffId, taskId, false, false );
                        stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
                        console.log('stafftimelogs---',stafftimelogs);
                        
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray = subData?.sub_task_id? subData?.sub_task_id?.split(",") : []|| [];
                                console.log('subTaskArray',subTaskArray)
                                if(subTaskArray.length==0){
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        totalHours = duration.asHours();
                                        console.log('totalHourstotalHours',totalHours)
                                        subData['hours'] = totalHours
                                        if (!isNaN(totalHours)) {
                                            newhours += totalHours;
                                        }
                                    }
                                }else{
                                    for (const sub of subTaskArray) {
                                    console.log('subTaskArray sub',sub)

                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        totalHours = duration.asHours();
                                        console.log('totalHourstotalHours',totalHours)
                                        subData['hours'] = totalHours
                                        if (!isNaN(totalHours)) {
                                            newhours += totalHours;
                                        }
                                    }
                                    }
                                }
                            }
                        }
                        requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
                        let hasHandledLabour10 = false;
                        for(const item of requestServices){
                            if(projectTaskDetails.service_id == item.labour_cost_service_id){
                                if (item.labour_cost_service_id === 10) {
                                    if (hasHandledLabour10) continue; 
                                    hasHandledLabour10 = true;
                                    }
                                let payoutData = await JobCost.fetchAllPayOutByProjectId(projectId, userId);
                                if(payoutData && payoutData?.length > 0){
                                    let servicePayOutTotal = payoutData?.reduce((total, row) => total + (row.amount || 0), 0);
                                    const totalPayoutAmount = payoutData?.reduce((acc, row) => {
                                        return row.service_id === item.id ? acc + (row.amount || 0) : acc;
                                    }, 0);
                                    console.log('gfffffffffd',newhours,staffHourlyRate,totalPayoutAmount, servicePayOutTotal)
                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_unit_cost : staffHourlyRate || 0,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : 1
                                    }
                                    console.log('gfffffffffd 2',data)
                                    if(userId ===1){
                                        let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
                                    }
                                }
                            }
                        }
                        let allPayOut = await JobCost.fetchAllPayOutByProjectId(projectId, userId);
                         requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
                        if(requestServices?.length>0){
                            console.log('selectedServicessssssssss 1', requestServices)
                            for (const row of requestServices) {
                            // if (row.taken !== 1) continue;
                            console.log('selectedServicessssssssss 2', row)
                            //  let unitCost = parseFloat(row.unit_cost).toFixed(2) 
                            const servicePayOutTotal = allPayOut?.reduce((acc, item) => {
                                return item.service_id === row.id ? acc + (item.amount || 0) : acc;
                            }, 0);
                            const serviceHoursTotal = allPayOut?.reduce((acc, item) => {
                                return item.service_id === row.id ? acc + (item.hours || 0) : acc;
                            }, 0);
                    
                            // const unitCost = 
                            //   parseFloat(row.jobcost_unit_cost) > 0
                            //     ? parseFloat(row.jobcost_unit_cost)
                            //     : parseFloat(row.originalCost) || 0;
                            const unitCost = parseFloat(row.originalCost) || 0;
                            // Quantity: keep whatever is in jobcost_quantity—even 0 / "0.00"
                            const jobQty =
                                row.jobcost_quantity != null && row.jobcost_quantity !== ''
                                ? parseFloat(row.jobcost_quantity)            // "0.00" → 0
                                : parseFloat(row.qty) || 0;   
                            console.log('selectedServicessssssssss 3', unitCost ,jobQty ) 
                            console.log('selectedServicessssssssss 4', Number((unitCost * jobQty).toFixed(2)) ) 
                            console.log('selectedServicessssssssss 5', servicePayOutTotal ) 
                            console.log('selectedServicessssssssss serviceHoursTotal', serviceHoursTotal ) 
                            let requestProduct = {}
                            requestProduct['taken'] = 1,
                            requestProduct['jobcost_unit_cost']  = unitCost.toFixed(2);         
                            requestProduct['jobcost_quantity']   = serviceHoursTotal || jobQty;                       
                            requestProduct['jobcost_total_cost'] = (servicePayOutTotal > 0) ? servicePayOutTotal : Number((unitCost * jobQty).toFixed(2));
                            // requestProduct['jobcost_unit_cost'] = unitCost || 0
                            // requestProduct['jobcost_quantity'] = row.jobcost_quantity || row.qty || 0
                            // requestProduct['jobcost_total_cost'] =  unitCost * Number(row.jobcost_quantity) || 0
                            console.log('selectedServicessssssssss 6', requestProduct)
                            let response = await Request.updateRequestServices(requestProduct,row.id,row.request_id)
                            console.log('responseeeeeeeeeeeeee', response)
                    
                            }
                        }
                    // }
                }
                
                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);
                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);
                    }
                }
                reply.send({ status:1, message:"Task Timelog added successfully",result:'update',
                    notificationMsg:notificationMsg, projectTaskDetails,requestServices })
            }else{
                reply.send({status:0, message:"Failed to add payout"})
            }
        }else{
            reply.send({status:0, message:"Failed to update timelog"})
        }
    }catch(error){
        console.log("Update staff task timelog error : ",error);
        reply.send({ status:500, message:"Failed to delete timelog", error:error,errorMessage:error.message })
    }
}

const handleDesignOrderTimelogPayout = async (req, reply) => {

     const {taskId, projectId,userId, endTime, startTime, staffId, staff, staffHourlyRate, hours, totalAmount,cover,description} = req.body
  try {
    const timelogData = {
      design_order_id: projectId,
      task_id: taskId,
      sub_task_id: null,
      user_id: staffId,
      start_time: startTime,
      end_time: endTime || startTime,
      status: 1,
      noSubTask: 0,
    };

    const addStaffTaskTimelog = await Request.addDesignOrderStaffTaskTimelog(timelogData);
    console.log('addStaffTaskTimelog',addStaffTaskTimelog)
    if (!addStaffTaskTimelog) {
      return reply.send({ status: 0, message: "Failed to update timelog" });
    }

    const payoutData = {
      design_order_id: projectId,
      task_id: taskId,
      log_id: null,
      team: staff.id,
      paid_at: startTime,
      end_date: endTime,
      hours,
      amount: totalAmount,
      timestamp: moment().unix(),
      is_time_tracking: 0,
      added_by: userId,
      status: userId === 1 ? 1 : 5,
      is_auto_pay: 0,
      cover,
      description,
    };

    const insertedstatus = await Request.addDesignOrderPayOut(payoutData);
    console.log('insertedstatus',insertedstatus)
    if (!insertedstatus) {
      return reply.send({ status: 0, message: "Failed to add payout" });
    }

    // Send email if admin and cover is present
    if (userId == 1 && cover) {
      await sendReceiptEmail(cover);
    } else {
      console.log("Need approval");
    }
    // const projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
    //     if(projectTaskDetails?.length > 0){
    //         projectTaskDetails = projectTaskDetails[0];
    //         stafftimelogs = await Request.fetchDesignOrderStaffTaskTimelog( false, false, taskId, false, false );
    //         console.log('stafftimelogs---',stafftimelogs);    
    //     if (stafftimelogs && stafftimelogs?.length > 0) {
    //         for (const subData of stafftimelogs) {
    //             let subTaskArray = subData?.sub_task_id? subData?.sub_task_id?.split(",") : []|| [];
    //             console.log('subTaskArray',subTaskArray)
    //             if(subTaskArray.length==0){
    //                 if (parseInt(subData.task_id) == taskId) {
    //                     const startMoment = moment.unix(subData.start_time);
    //                     let endMoment;
    //                     if (subData.end_time !== null) {
    //                         endMoment = moment.unix(subData.end_time);
    //                     } else {
    //                         endMoment = moment();
    //                     }
    //                     const duration = moment.duration(endMoment.diff(startMoment));
    //                     totalHours = duration.asHours();
    //                     console.log('totalHourstotalHours',totalHours)
    //                     subData['hours'] = totalHours
    //                     if (!isNaN(totalHours)) {
    //                         newhours += totalHours;
    //                     }
    //                 }
    //             }else{
    //                 for (const sub of subTaskArray) {
    //                 console.log('subTaskArray sub',sub)

    //                 if (parseInt(subData.task_id) == taskId) {
    //                     const startMoment = moment.unix(subData.start_time);
    //                     let endMoment;
    //                     if (subData.end_time !== null) {
    //                         endMoment = moment.unix(subData.end_time);
    //                     } else {
    //                         endMoment = moment();
    //                     }
    //                     const duration = moment.duration(endMoment.diff(startMoment));
    //                     totalHours = duration.asHours();
    //                     console.log('totalHourstotalHours',totalHours)
    //                     subData['hours'] = totalHours
    //                     if (!isNaN(totalHours)) {
    //                         newhours += totalHours;
    //                     }
    //                 }
    //                 }
    //             }
    //         }
    //     }
    // }

    // Add notification
    const notificationMsg = `New Pay Out has been added`;
    const notificationUrl = "staff-payout";

    await Admin.incrementField(userId, "noti_count", 1);
    await Admin.addNotification({
      user_id: userId,
      url: notificationUrl,
      timestamp: currentDate,
      message: notificationMsg,
      status: 1,
      from_id: userId,
    });

    const adminIds = await Admin.getAllAdminIds();
    for (const adminId of adminIds) {
      if (adminId !== userId) {
        await Admin.incrementField(adminId, "noti_count", 1);
        await Admin.addNotification({
          user_id: adminId,
          url: notificationUrl,
          timestamp: currentDate,
          message: notificationMsg,
          status: 1,
          from_id: userId,
        });
      }
    }

    return reply.send({
      status: 1,
      message: "Design Order Timelog added successfully",
      result: 'update',
      notificationMsg,
      projectTaskDetails: null,
      requestServices: null
    });

  } catch (error) {
    console.log("Design order error:", error);
    return reply.send({ status: 500, message: "Failed to process design order", error, errorMessage: error.message });
  }
};

const approveManualStaffTaskTimelog = async (req, reply) => {
    try{
        const { payoutData,userId,} = req.body
      
        let taskId = payoutData.task_id
        let projectId = payoutData.project_id
        let staffHourlyRate = payoutData.hourly_rate
        let cover = payoutData.cover

        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let totalHours = 0;
        let currentDate = Math.round(moment().valueOf() / 1000);
        if(true){
            let data = {
                status:1,
                id:payoutData.id
            };
            const insertedstatus = await JobCost.updatePayOut(data,data.id)
            if(insertedstatus){

                try {
                        await sendReceiptEmail(cover);
                    
                        } catch (error) {
                            console.log('error',error)
                        }

                projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
                if(projectTaskDetails?.length > 0){
                    projectTaskDetails = projectTaskDetails[0];
                    // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
                        // stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, staffId, taskId, false, false );
                        stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
                        console.log('stafftimelogs---',stafftimelogs);
                        
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray =subData?.sub_task_id? subData?.sub_task_id?.split(",") : []|| [];
                                console.log('subTaskArray',subTaskArray)
                                if(subTaskArray.length==0){
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        totalHours = duration.asHours();
                                        console.log('totalHourstotalHours',totalHours)
                                        subData['hours'] = totalHours
                                        if (!isNaN(totalHours)) {
                                            newhours += totalHours;
                                        }
                                    }
                                }else{
                                    for (const sub of subTaskArray) {
                                    console.log('subTaskArray sub',sub)

                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        totalHours = duration.asHours();
                                        console.log('totalHourstotalHours',totalHours)
                                        subData['hours'] = totalHours
                                        if (!isNaN(totalHours)) {
                                            newhours += totalHours;
                                        }
                                    }
                                    }
                                }
                            }
                        }
                        requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
                        for(const item of requestServices){
                            if(projectTaskDetails.service_id == item.labour_cost_service_id){
                                let payoutData = await JobCost.getPayOutByTaskId(projectId,taskId);
                                if(payoutData && payoutData?.length > 0){
                                    let servicePayOutTotal = payoutData?.reduce((total, row) => total + (row.amount || 0), 0);
                                    const totalPayoutAmount = payoutData?.reduce((acc, row) => {
                                        return row.service_id === item.id ? acc + (row.amount || 0) : acc;
                                    }, 0);
                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_unit_cost : staffHourlyRate || 0,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : 1
                                    }
                                    let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
                                }
                            }
                        }
                    // }
                }
                
                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);
                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);
                    }
                }
                reply.send({ status:1, message:"Task Timelog added successfully",result:'update',
                    notificationMsg:notificationMsg, projectTaskDetails,requestServices })
            }else{
                reply.send({status:0, message:"Failed to add payout"})
            }
        }else{
            reply.send({status:0, message:"Failed to update timelog"})
        }
    }catch(error){
        console.log("Update staff task timelog error : ",error);
        reply.send({ status:500, message:"Failed to delete timelog", error:error,errorMessage:error.message })
    }
}

const approveDesignManualStaffTaskTimelog = async (req, reply) => {
    try{
        const { payoutData,userId,} = req.body
      
        let taskId = payoutData.task_id
        let projectId = payoutData.project_id
        let staffHourlyRate = payoutData.hourly_rate
        let cover = payoutData.cover

        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let totalHours = 0;
        let currentDate = Math.round(moment().valueOf() / 1000);
        if(true){
            let data = {
                status:1,
                id:payoutData.id
            };
            const insertedstatus = await Request.updateDesignPayOut(data,data.id)
            if(insertedstatus){

                try {
                        await sendReceiptEmail(cover);
                    
                        } catch (error) {
                            console.log('error',error)
                        }

                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);
                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);
                    }
                }
                reply.send({ status:1, message:"Task Timelog added successfully",result:'update',
                    notificationMsg:notificationMsg, projectTaskDetails,requestServices })
            }else{
                reply.send({status:0, message:"Failed to add payout"})
            }
        }else{
            reply.send({status:0, message:"Failed to update timelog"})
        }
    }catch(error){
        console.log("Update staff task timelog error : ",error);
        reply.send({ status:500, message:"Failed to delete timelog", error:error,errorMessage:error.message })
    }
}

const deleteManualStaffTaskTimelog = async (req, reply) => {
    try{
        const {editId,staffId} = req.body
        const payoutData = await JobCost.getPayOutById(editId);
        console.log('payoutDatapayoutData',payoutData)
        const taskId = payoutData[0]?.task_id
        const projectId = payoutData[0]?.project_id
        const staff = payoutData[0]?.team
        const startTime = payoutData[0]?.paid_at
        const endTime = payoutData[0]?.end_date
        // const staffId = payoutData[0]?.task_id

        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let totalHours = 0;
        let currentDate = Math.round(moment().valueOf() / 1000);

        const deleteStaffTaskTimelog = await ProjectTask.deleteStaffTaskTimelogsForPayout(projectId,taskId,staffId,startTime,endTime);
        console.log('deleteStaffTaskTimeLogdesign' , deleteStaffTaskTimelog)
        if(deleteStaffTaskTimelog){
            const deletedstatus = await JobCost.deletePayOut(editId);//projectId,taskId,startTime,endTime,staff)
            if(deletedstatus){
                projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
                if(projectTaskDetails?.length > 0){
                    projectTaskDetails = projectTaskDetails[0];
                    // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
                        // stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, staffId, taskId, false, false );
                        stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
                        console.log('stafftimelogs---',stafftimelogs);
                       
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray =subData?.sub_task_id? subData?.sub_task_id?.split(",") : [] ||[ ];
                                if(subTaskArray.length ===0){
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        totalHours = duration.asHours();
                                        subData['hours'] = totalHours
                                        if (!isNaN(totalHours)) {
                                            newhours -= totalHours;
                                        }
                                    }
                                }else{
                                    
                                for (const sub of subTaskArray) {
                                if (parseInt(subData.task_id) == taskId) {
                                    const startMoment = moment.unix(subData.start_time);
                                    let endMoment;
                                    if (subData.end_time !== null) {
                                        endMoment = moment.unix(subData.end_time);
                                    } else {
                                        endMoment = moment();
                                    }
                                    const duration = moment.duration(endMoment.diff(startMoment));
                                    totalHours = duration.asHours();
                                    subData['hours'] = totalHours
                                    if (!isNaN(totalHours)) {
                                        newhours -= totalHours;
                                    }
                                }
                                }
                            }
                            }
                        }
                        requestServices = await Request.getRequestServices(projectTaskDetails.request_id);
                        for(const item of requestServices){
                            if(projectTaskDetails.service_id == item.labour_cost_service_id){
                                let payoutData = await JobCost.getPayOutByTaskId(projectId,taskId);
                                if(payoutData && payoutData?.length > 0){
                                    let servicePayOutTotal = payoutData?.reduce((total, row) => total + (row.amount || 0), 0);
                                    const totalPayoutAmount = payoutData?.reduce((acc, row) => {
                                        return row.service_id === item.id ? acc + (row.amount || 0) : acc;
                                    }, 0);
                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : 1
                                    }
                                    let updateRequestServices = await Request.updateRequestServices(data,item.id,item.request_id)
                                }
                            }
                        }
                    // }
                }
                reply.send({ status:1, message:"Task Timelog updated successfully" });
            }else{
                reply.send({ status:0, message:"Failed to update payout" });
            }
        }else{
            reply.send({ status:0, message:"Failed to update timelog" });
        }
    }catch(error){
        console.log("Update staff task timelog error : ",error);
        reply.send({ status:500, message:"Failed to update timelog", error:error,errorMessage:error.message })
    }
}

const deleteManualStaffDesignTaskTimelog = async (req, reply) => {
    try{
        const {editId,staffId} = req.body
        console.log('edittttttid',editId)
        const payoutData = await Request.getDesignPayOutById(editId);
        console.log('design payoutDatapayoutDataaaaaaaaaa',payoutData)
        const taskId = payoutData[0]?.task_id
        const projectId = payoutData[0]?.design_order_id
        const staff = payoutData[0]?.team
        const startTime = payoutData[0]?.paid_at
        const endTime = payoutData[0]?.end_date
        // const staffId = payoutData[0]?.task_id

        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let totalHours = 0;
        let currentDate = Math.round(moment().valueOf() / 1000);

        const deleteStaffTaskTimelog = await Request.deleteDesignStaffTaskTimelogsForPayout(projectId,taskId,staffId,startTime,endTime);
        console.log('deleteStaffTaskTimeloggggggggggggg',deleteStaffTaskTimelog)
        if(deleteStaffTaskTimelog){
            const deletedstatus = await Request.deleteDesignPayOut(editId);
            console.log('deletedstatuss11',deletedstatus)
            if(deletedstatus){
                reply.send({ status:1, message:"Task Timelog updated successfully" });
            }else{
                reply.send({ status:0, message:"Failed to update payout" });
            }
            // if(deletedstatus){
            //     projectTaskDetails = await ProjectTask.getProjectTaskById(taskId);
            //     if(projectTaskDetails?.length > 0){
            //         projectTaskDetails = projectTaskDetails[0];
            //             stafftimelogs = await ProjectTask.fetchStaffTaskTimelog( false, false, taskId, false, false );
            //             console.log('stafftimelogs---',stafftimelogs);
            //     }
            //     reply.send({ status:1, message:"Task Timelog updated successfully" });
            // }else{
            //     reply.send({ status:0, message:"Failed to update payout" });
            // }
        }else{
            reply.send({ status:0, message:"Failed to update timelog" });
        }
    }catch(error){
        console.log("Update staff task timelog error : ",error);
        reply.send({ status:500, message:"Failed to update timelog", error:error,errorMessage:error.message })
    }
}

const addDesignOrderTask = async (req, reply) => {
    try {
        let currentDate = Math.round(moment().valueOf() / 1000);
        let projectTask = {}
        projectTask['name'] = req.body.name;
        projectTask['design_order_id'] = req.body.projectId;
        projectTask['timestamp'] = currentDate;
        projectTask['userid'] = req.body.userId;
        projectTask['status'] = 1;
        projectTask['start_date'] = req.body.start ? req.body.start : null
        projectTask['due_date'] = req.body.end ? req.body.end : null
        projectTask['description'] = req.body.description ? req.body.description : null
        projectTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectTask['priority'] = req.body.priority ? req.body.priority : null
        projectTask['cover_image'] = req.body.cover_image ? req.body.cover_image : 'null'
        projectTask['complete'] = 0
        projectTask['complete_sync'] = 1
        projectTask['from_product']=0
        let userId = req.body.userId
        const projectTaskId = await ProjectTask.addDesignOrderTask(projectTask);

        if (projectTaskId) {
            let allSubtask=await ProjectTask.getAllProjectTasks(req.body.projectId,1,userType=1)
            let  firstTaskStatus=allSubtask[0].status
            const sumCompletionTask = allSubtask.reduce((acc, task) => acc + task.complete, 0);
            const averageCompletionTask = sumCompletionTask / allSubtask.length;
            const tasksWithStatusCompletedTasks = allSubtask.every(task => task.status === firstTaskStatus);
            let projectTaskData = {};
            projectTaskData.completion=averageCompletionTask
            if(tasksWithStatusCompletedTasks){
                projectTaskData.status=firstTaskStatus
            }else{
                projectTaskData.status=1
            }
            let resultStatus = await Project.updateProject(req.body.projectId,projectTaskData);
            let notificationMsg = "New job task has been added."
            let notificationUrl = "projects/view-project/" + req.body.projectId
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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);

                }
            }
            reply.send({ status: 1, message: "New job task has been added" });
        }
        else {
            reply.send({ status: 0, message: "Failed to add new job task " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }

}
const updateDesignOrderTask = async (req, reply) => {
    try {
        let currentDate = Math.round(moment().valueOf() / 1000);
        let projectTask = {}
        let taskId = req.body.id;
        projectTask['name'] = req.body.name;
        projectTask['start_date'] = req.body.start ? req.body.start : null
        projectTask['due_date'] = req.body.end ? req.body.end : null
        projectTask['description'] = req.body.description ? req.body.description : null
        projectTask['reporter_id'] = req.body.reporter ? req.body.reporter : 1
        projectTask['priority'] = req.body.priority ? req.body.priority : null
        projectTask['cover_image'] = 'null'
        projectTask['complete'] = 0
        //cover image upload
        let userId = req.body.userId
        const updated = await ProjectTask.updateProjectTask(projectTask, taskId);
        if (updated) {


            let notificationMsg = "Project task has been updated."
            let notificationUrl = "projects/view-project-task/" + taskId
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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);

                }
            }
            reply.send({ status: 1, message: "Job task has been updated" });
        }
        else {
            reply.send({ status: 0, message: "Failed to update job task " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }

}
const updatateDesignOrderTaskStatus = async (req, reply) => {
    try {
        let { status, taskId, userId,projectId } = req.body
        let currentDate = moment().unix();
        let projectTask = {}
        projectTask['status'] = status;
        let projectTaskDetails = await ProjectTask.getProjectTaskBytaskId(taskId)
        const updated = await ProjectTask.updateProjectTask(projectTask, taskId);
        if (updated) {

            let notificationMsg = `The status of the job "${projectTaskDetails[0]['name']}" Task has been Updated`
            let notificationUrl = "projects/view-project-task/" + taskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);

                }
            }

            reply.send({ status: 1, message: "Project Task status  has been Updated" });
        }
        else {
            reply.send({ status: 0, message: "Failed to update Project task status " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }


}

const addDesignOrderAttachments=async(req,reply)=>{
    try{
        let { userId, secTab, userType, attachments,designs, projectId } = req.body;
    let currentTime = moment().unix()

        // Get userType from users table to validate
        const userData = await Admin.getUserById(userId);
        const actualUserType = userData && userData[0] ? userData[0].user_type : null;

        const urlObjects = [];
        for (const key in attachments) {
            if (attachments.hasOwnProperty(key)) {
                const urls = attachments[key];
                urls.forEach(url => {
                    urlObjects.push({ url });
                });
            }
        }
        console.log('urlObjects==urlObjects=',urlObjects)
        console.log('urlObjects==attachments=',attachments)
        console.log('urlObjects==designs=',designs)
        console.log('urlObjects==secTab=',secTab)
        
        // Check if this is the first attachment for this design order
        const existingAttachments = await Request.fetchAllDesignOrderAttachments(projectId);
        const isFirstAttachment = !existingAttachments || existingAttachments.length === 0;
        
        let inserted=""
        for (const [fileType, files] of Object.entries(designs || {})) {
            for (const file of files) {
                let approvedImage = {};
                approvedImage.name = file.downloadURL || file.url || file;
                approvedImage.file_type = file.fileType || file.file_type;
                approvedImage.extension = (file.extension || (approvedImage.name && String(approvedImage.name).split('.').pop().split('?')[0]) || '').toLowerCase();
                approvedImage.file_size = file.size || file.file_size || 0;
                approvedImage.design_order_id = projectId;
                approvedImage.added_by = userId;
                approvedImage.timestamp = moment().unix();
                approvedImage.isDesign = secTab == 'Designs' ? 1 : 2;
                approvedImage.isNew =secTab == 'Designs' ? 1 : 2,
                approvedImage.is_reference = secTab == 'References' ? 1 : 0;
                if (approvedImage.extension === 'pdf') {
                    approvedImage.file_type = 'application/pdf';
                }
                console.log('urlObjects==approvedImage=',approvedImage)
                inserted = await Request.addDesignOrderAttachments(approvedImage);
                // const isPdfFile = approvedImage.file_type === 'application/pdf' || approvedImage.file_type === 'pdf' || approvedImage.extension === 'pdf';
                // if (isPdfFile && inserted) {
                //     try {
                //         await convertDesignOrderPdfToPngHelper(inserted);
                //         console.log(`PDF conversion completed for design order attachment ID: ${inserted}`);
                //     } catch (conversionError) {
                //         console.error(`Error converting PDF for design order attachment ${inserted}:`, conversionError);
                //     }
                // }
            }
        }
        if(inserted){
            if(secTab == 'Designs'){
                // const data={
                //     status: 1,
                //     send_client_app_req :0,
                //     design_order_job_status:2
                // }
                const fundDesignOrderById = await Request.getDesignOrderByIdNew(projectId)
                console.log('fundDesignOrderById',fundDesignOrderById)
                const designOrder = fundDesignOrderById[0];
                console.log("designOrderdesignOrder",designOrder)
                let previousStatus = designOrder?.dataValues?.status;
                let clientId = designOrder?.dataValues?.client;
                let currentJobStatus = designOrder?.dataValues?.design_order_job_status;

                // Check if userType is 11 and current design_order_job_status is 1, 3, or 4
                let shouldUpdateJobStatus = false;
                if (actualUserType === 11 && (currentJobStatus === 1 || currentJobStatus === 4)) { // || currentJobStatus === 3
                    shouldUpdateJobStatus = true;
                }
                // If this is the first attachment, set design_order_job_status to 2 (in progress)
                if (isFirstAttachment && currentJobStatus == 1) {
                    shouldUpdateJobStatus = true;
                }
                console.log('UserType validation:', { actualUserType, currentJobStatus, shouldUpdateJobStatus, isFirstAttachment });

                const data={
                    status: 1,
                    send_client_app_req :0,
                    design_order_job_status: shouldUpdateJobStatus ? 2 : currentJobStatus,
                    working_designer_id: actualUserType === 11 ? userId : designOrder?.dataValues?.working_designer_id
                }
                const clientUserId = await Client.getClientById(clientId)
                console.log('clientUserId===',clientUserId)
                if(designOrder?.dataValues?.status !== 3 ){
                    const updateDesignOrder = await Request.updateDesignOrders(projectId,data)
                    console.log("designOrderdesignOrder updateDesignOrder",updateDesignOrder)

                    // const allUserIds = await Admin.getAllUserIds();
                    // let usersToUpdate = [...new Set([userId,clientUserId?.user_id, ...allUserIds].filter(Boolean))];

                    // const updateCounts = async (userId) => {
                    //     if (previousStatus === 2) {
                    //         await Request.designCountIncrementField(userId, "approved_count", -1, "approved_count_ids", projectId, false);
                    //         await Request.designCountIncrementField(userId, "open_count", 1, "open_count_ids", projectId, true);
                    //     } else if (previousStatus === 6) {
                    //         await Request.designCountIncrementField(userId, "rejected_count", -1, "rejected_ids", projectId, false);
                    //         await Request.designCountIncrementField(userId, "open_count", 1, "open_count_ids", projectId, true);
                    //     }
                    // };

                    // await Promise.all(usersToUpdate.map(user => updateCounts(user)));
                    // console.log("Successfully updated counts for Open transition.");
                }

                // Add update entry for Job Log
                const userData = await Admin.getUserById(userId);
                const userName = userData && userData[0] ? `${userData[0].first_name} ${userData[0].last_name}` : 'Unknown User';
                const designCount = Object.values(designs).flat().length;
                const designText = designCount === 1 ? 'design' : 'designs';
                const notification_msg = `🎨 <strong>${userName}</strong> added ${designCount} ${designText} to the design order "<strong>${designOrder?.dataValues?.name || 'Design Order'}</strong>".`;

                if (!empty(notification_msg)) {
                    let requestActivity = {}
                    requestActivity['design_order_id'] = projectId;
                    requestActivity['activity'] = notification_msg;
                    requestActivity['added_by'] = userId
                    requestActivity['timestamp'] = currentTime
                    let reqActivityId = await RequestActivity.addDesignOrderUpdate(requestActivity);
                }


                let notificationMsg = "Design added successfully "
                let notificationUrl = "design-order-job/view-project/";
                let notificationData = {};
                const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
                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();

                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);

                    }
                }
                reply.send({status:1,message:"Design added successfully"})
            }else if (secTab == 'References'){
                let notificationMsg = "Reference added successfully "
                let notificationUrl = "design-order-job/view-project/";
                let notificationData = {};
                const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
                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();

                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);

                    }
                }

                // Add log entry to design_order_updates table for reference attachment
                let referenceActivityMsg = `📎 The Design Order has been updated. A new Reference has been uploaded`
                if (!empty(referenceActivityMsg)) {
                    let requestActivity = {}
                    requestActivity['design_order_id'] = projectId;
                    requestActivity['activity'] = referenceActivityMsg;
                    requestActivity['added_by'] = userId
                    requestActivity['timestamp'] = currentTime
                    let reqActivityId = await RequestActivity.addDesignOrderUpdate(requestActivity);
                }

                reply.send({status:1,message:"Reference added successfully"})
            } else{
                const fundDesignOrderById = await Request.getDesignOrderByIdNew(projectId)
                console.log('fundDesignOrderById',fundDesignOrderById)
                const designOrder = fundDesignOrderById[0];
                console.log("designOrderdesignOrder",designOrder)
                let previousStatus = designOrder?.dataValues?.status;
                let clientId = designOrder?.dataValues?.client;
                let currentJobStatus = designOrder?.dataValues?.design_order_job_status;

                // Check if userType is 11 and current design_order_job_status is 1, 3, or 4
                let shouldUpdateJobStatus = false;
                if (actualUserType === 11 && (currentJobStatus === 1 || currentJobStatus === 4)) { // || currentJobStatus === 3
                    shouldUpdateJobStatus = true;
                }
                // If this is the first attachment, set design_order_job_status to 2 (in progress)
                if (isFirstAttachment && currentJobStatus == 1 ) {
                    shouldUpdateJobStatus = true;
                }
                console.log('UserType validation for Files:', { actualUserType, currentJobStatus, shouldUpdateJobStatus, isFirstAttachment });

                const data={
                    status: 1,
                    send_client_app_req :0,
                    design_order_job_status: shouldUpdateJobStatus ? 2 : currentJobStatus,
                    working_designer_id: actualUserType === 11 ? userId : designOrder?.dataValues?.working_designer_id
                }
                const clientUserId = await Client.getClientById(clientId)
                console.log('clientUserId===',clientUserId)
                if(designOrder?.dataValues?.status !== 3 ){
                    const updateDesignOrder = await Request.updateDesignOrders(projectId,data)
                    console.log("designOrderdesignOrder updateDesignOrder",updateDesignOrder)
                }

                let notificationMsg = "File added successfully "
                let notificationUrl = "design-order-job/view-project/";
                let notificationData = {};
                const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
                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();

                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);

                    }
                }
                reply.send({status:1,message:"File added successfully"})
            }
        }
        else{
            reply.send({status:0, message:"Failed to add design"})
        }
    }catch(error){
        console.log('Error adding design',error);
        reply.send({status:0, message:"Failed to add design",error})
    }
}

const fetchDesignOrderAttachments=async(req, reply)=>{
    let {projectId}=req.body
    let attachments = await Request.fetchAllDesignOrderAttachments(projectId);
    let reference_attachments = await Request.fetchAllDesignOrderReferenceAttachments(projectId);
    if(attachments || reference_attachments){
        reply.send({status:1, attachments:attachments || [], reference_attachments: reference_attachments || []})
    }
    else{
        reply.send({status:0, message:"Failed to fetch attachments"})
    }
}

const deleteDesignOrderAttachments=async(req, reply)=>{
    let {userId,userType,attachments,projectId}=req.body
    let currentDate = moment().unix();
    
    // Get design details before deletion for Job Log
    const sequelize = require('../config/dbconnection');
    let designDetails = [];
    if (attachments && attachments.length > 0) {
        const attachmentIds = attachments.join(',');
        const designQuery = await sequelize.query(`
            SELECT doa.*, do.name as design_order_name
            FROM design_order_attachments doa
            LEFT JOIN design_orders do ON do.id = doa.design_order_id
            WHERE doa.id IN (${attachmentIds})
        `);
        designDetails = designQuery[0] || [];
    }
    
    let deleted = await Request.deleteDesignOrderAttachmentsBulk(attachments);
    if(deleted){
        // Add update entry for Job Log
        if (userId && designDetails.length > 0) {
            const userData = await Admin.getUserById(userId);
            const userName = userData && userData[0] ? `${userData[0].first_name} ${userData[0].last_name}` : 'Unknown User';
            const designCount = designDetails.length;
            const designText = designCount === 1 ? 'design' : 'designs';
            const designOrderName = designDetails[0]?.design_order_name || 'Design Order';
            const activityMsg = `<strong>${userName}</strong> deleted ${designCount} ${designText} from the design order "<strong>${designOrderName}</strong>".`;
            
            let requestActivity = {
                design_order_id: projectId,
                activity: activityMsg,
                added_by: userId,
                timestamp: currentDate
            };
            await RequestActivity.addDesignOrderUpdate(requestActivity);
        }
        
        let notificationMsg = "Attachments deleted from design order"
        let notificationUrl = "design-order-job/view-project/"+projectId;
        let notificationData = {};


        const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
        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();

        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);

            }
        }
        reply.send({status:1, message:"Attachments deleted successfully"})
    }else{
        reply.send({status:0, message:"Failed to delete attachments"})
    }
}

const viewDesignOrderSubTask = async (req, reply) => {
    let { id } = req.body
    let projectSubTask = await ProjectTask.getProjectDesignOrderSubTaskById(id);
    if (projectSubTask) {
        reply.send({
            status: 1,
            result: projectSubTask,
            // projectMembers,
            msg: "Project sub task fetched successfully"
        });
    }
    else {
        reply.send({ 'status': 0, msg: "Failed to fetch job sub task", });
    }
}

const updatateDesignOrderProjectSubTaskStatus = async (req, reply) => {
    try {
        let { status, subTaskId, userId,task,projectId } = req.body
        let currentDate = moment().unix();
        let projectTask = {}
        projectTask['status'] = status;
        let projectTaskDetails = await ProjectTask.getProjectDesignOrderSubTaskById(subTaskId)
        const updated = await Request.updateDesignOrdersSubTask(projectTask, subTaskId);

        if (updated) {
            let projectSubTask = await Request.getAllDesignOrderProjectSubTaskBytaskId(task,userType=1);

            const tasksWithStatusCompleted = projectSubTask.every(task => task.status === status);
            const subTasksComplete = projectSubTask.filter(task => task.status === 3);
            let completion=0
            if(!empty(subTasksComplete)){
                let data=100/projectSubTask.length
                completion=data*subTasksComplete.length
            }else{
                completion=0
            }
            const subTasksNew = projectSubTask.filter(task => task.status === 1);
            let project = {};
            project.complete=completion
            if(tasksWithStatusCompleted){
                project.status=status
            }else{
                project.status=subTasksNew?.length>0 ? 1 : 2
            }
            let result = await Request.updateDesignOrderService(project,task);
            
            let allTask=await Request.getAllDesignOrderTasks(projectId,userId,userType=1)
            const sumCompletionTask = allTask.reduce((acc, task) => acc + task.complete, 0);
            const averageCompletionTask = sumCompletionTask / allTask.length;
            const tasksWithStatusCompletedTasks = allTask.every(task => task.status === status);
            let taskCompleted=allTask.some(task => task.status === status);
            const TasksNew = allTask.filter(task => task.status === 1);
            let allTasksComplete = allTask.every(task => task.status === 1);

            let projectTaskData = {};
            projectTaskData.completion=averageCompletionTask
            if(tasksWithStatusCompletedTasks){
                projectTaskData.design_order_job_status=status
            }else{
               projectTaskData.design_order_job_status=TasksNew?.length>0?1:2
            }
            projectTaskData['timestamp'] = currentDate;
            let resultStatus = await Request.updateDesignOrders(projectId,projectTaskData);
            let updatedTask=await Request.getAllDesignOrderTasks(projectId,userId,userType=1)
            console.log('updatedTask',updatedTask)
            const readyForInstallation = updatedTask.every(task => task.status === 3);
            if (readyForInstallation) {
                console.log('All tasks completed',readyForInstallation);
            } else {
                console.log('Some tasks are not completed',readyForInstallation);
            }
            let notificationMsg = `The status of the Design Order Sub Task "${projectTaskDetails[0]['name']}" has been Updated`
            let notificationUrl = "design-order-job/view-project-sub-task/" + subTaskId;
            let notificationData = {};


            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);
                }
            }
            reply.send({ status: 1, message: "Design Order Sub Task status has been Updated",readyForInstallation });
        }
        else {
            reply.send({ status: 0, message: "Failed to update design order sub task status ",readyForInstallation:false });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }
}

const updatateDesignOrderJobHoldStatus = async (req, reply) => {
    try {
        let { projectId, userId, reason = '' } = req.body
        let currentDate = moment().unix();
        let project = {}
        let projectDetails = await Request.getAllDesignOrders(projectId,userId,userType=1);
        projectDetails = projectDetails?.data?.[0] || null;
        let previousStatus = projectDetails.status;
        console.log('previousStatus===',previousStatus)
        let clientId = projectDetails.client;
        const clientUserId = await Client.getClientById(clientId)
        console.log('clientUserId===',clientUserId)
        if(projectDetails?.hold==0){
            project['hold'] = 1;
            project['hold_reason'] = reason
        }else{
            project['hold'] = 0;
            project['hold_reason'] = reason
        }
        project['timestamp'] = currentDate;
        let updated = await Request.updateDesignOrders(projectId,project);
        // const allUserIds = await Admin.getAllUserIds();
        // let usersToUpdate = [...new Set([userId,clientUserId?.user_id, ...allUserIds].filter(Boolean))];

        // const updateCounts = async (userId) => {
        //     if (project.hold === 1) { 
        //         // Moving to Hold: Remove from previous count, Add to hold_count_ids
        //         if (previousStatus == 1) {
        //             await Request.designCountIncrementField(userId, "open_count", -1, "open_count_ids", projectId, false);
        //         } else if (previousStatus == 2) {
        //             await Request.designCountIncrementField(userId, "approved_count", -1, "approved_count_ids", projectId, false);
        //         } else if (previousStatus == 6) {
        //             await Request.designCountIncrementField(userId, "rejected_count", -1, "rejected_ids", projectId, false);
        //         }
        //         if (projectDetails?.design_order_job_status == 1){
        //             await Request.designCountIncrementField(userId, "new_count", -1, "new_count_ids", projectId, false);
        //         }else if(projectDetails?.design_order_job_status == 2){
        //             await Request.designCountIncrementField(userId, "in_progress_count", -1, "in_progress_count_ids", projectId, false);
        //         }
        //         await Request.designCountIncrementField(userId, "hold_count", 1, "hold_count_ids", projectId, true);
        //         await Request.designCountIncrementField(userId, "job_hold_count", 1, "job_hold_count_ids", projectId, true);
        //     } else { 
        //         // Removing from Hold: Remove from hold_count_ids, Restore to previous status count
        //         await Request.designCountIncrementField(userId, "hold_count", -1, "hold_count_ids", projectId, false);
        //         await Request.designCountIncrementField(userId, "job_hold_count", -1, "job_hold_count_ids", projectId, false);
        //         if (previousStatus == 1) {
        //             await Request.designCountIncrementField(userId, "open_count", 1, "open_count_ids", projectId, true);
        //         } else if (previousStatus == 2) {
        //             await Request.designCountIncrementField(userId, "approved_count", 1, "approved_count_ids", projectId, true);
        //         } else if (previousStatus == 6) {
        //             await Request.designCountIncrementField(userId, "rejected_count", 1, "rejected_ids", projectId, true);
        //         }
        //         if (projectDetails?.design_order_job_status == 1){
        //             await Request.designCountIncrementField(userId, "new_count", 1, "new_count_ids", projectId, true);
        //         }else if(projectDetails?.design_order_job_status == 2){
        //             await Request.designCountIncrementField(userId, "in_progress_count", 1, "in_progress_count_ids", projectId, true);
        //         }
        //     }
        // };
        

        // await Promise.all(usersToUpdate.map(user => updateCounts(user)));
        // console.log("updateddddddd hold status count")
        if (updated) {
            // Add update entry for Job Log
            const userData = await Admin.getUserById(userId);
            const userName = userData && userData[0] ? `${userData[0].first_name} ${userData[0].last_name}` : 'Unknown User';
            let activityMsg = "";
            if(project?.hold==1){
                activityMsg = reason 
                    ? `<strong>${userName}</strong> moved the design order "<strong>${projectDetails?.name}</strong>" to Hold. Reason: ${reason}`
                    : `<strong>${userName}</strong> moved the design order "<strong>${projectDetails?.name}</strong>" to Hold.`;
            } else{
                activityMsg = `<strong>${userName}</strong> removed the design "<strong>${projectDetails?.name}</strong>" from Hold.`;
            }
            
            let requestActivity = {
                design_order_id: projectId,
                activity: activityMsg,
                added_by: userId,
                timestamp: currentDate
            };
            await RequestActivity.addDesignOrderUpdate(requestActivity);
            
            // let teamMembers = await Project.getAllTeam(projectId)
            let notificationMsg = ""
            if(project?.hold==1){
            notificationMsg = `The design order "${projectDetails?.name}" has been moved to Hold`
            } else{
            notificationMsg = `The design order "${projectDetails?.name}" has been removed from Hold`
            }
            let notificationUrl = "design-order-job/view-project/" + projectId;
            let notificationData = {};

            // for (const team of teamMembers) {
            //     const incrementResult = await Admin.incrementField(userId, "noti_count", 1);
            //     notificationData = {
            //         user_id: team.userid,
            //         url: notificationUrl,
            //         timestamp: currentDate,
            //         message: notificationMsg,
            //         status: 1,
            //         from_id: userId,
            //     };
            //     const addNotificationResult = await Admin.addNotification(notificationData);
            // }
            const incrementResult_User = await Admin.incrementField(userId, "noti_count", 1);
            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();

            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);
                }
            }
            reply.send({ status: 1, message: notificationMsg });
        }
        else {
            reply.send({ status: 0, message: "Failed to update job status " });
        }
    }
    catch (error) {
        reply.status(500).send({ message: "Server error:" + error })
    }
}


const addDesignOrderStaffTaskTimelog = async (req, reply) => {
    try{
        const {checkedItems,taskId, projectId, checkedInstallations, driverUserID, userId,now, noSubTask, isDriver} = req.body
        const subtaskIds = checkedItems?.join(',');
        const installationIds = checkedInstallations?.join(',');
        let currentDate = Math.round(moment().valueOf() / 1000);
        
        // Get userType from users table to validate
        const userData = await Admin.getUserById(userId);
        const actualUserType = userData && userData[0] ? userData[0].user_type : null;
        
        let data = {}
        data.design_order_id = projectId || null
        data.task_id = taskId || null
        data.sub_task_id = subtaskIds || null
        data.noSubTask = noSubTask ? 1 : 0
        data.user_id = userId
        data.start_time = now ? now : currentDate
        data.status = 1
        const addStaffTaskTimelog = await Request.addDesignOrderStaffTaskTimelog(data);

        if(addStaffTaskTimelog){
            // Check if userType is 11 and update design_order_job_status if needed
            if(actualUserType === 11 && projectId){
                const fundDesignOrderById = await Request.getDesignOrderByIdNew(projectId)
                const designOrder = fundDesignOrderById[0];
                let currentJobStatus = designOrder?.dataValues?.design_order_job_status;

                // Check if current design_order_job_status is 1, 3, or 4
                if(currentJobStatus === 1 || currentJobStatus === 3 || currentJobStatus === 4){
                    const updateData = {
                        design_order_job_status: 2,
                        working_designer_id: userId
                    }
                    await Request.updateDesignOrders(projectId, updateData);
                    console.log('Updated design_order_job_status from 1 to 2 for userType 11');
                }
            }
            
            reply.send({status:1, message:"Timelog for task added successfully",result:'add'});
        }else{
            reply.send({status:0, message:"Failed to add timelog"});
        }
    }catch(error){
        console.log("Add staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to add timelog",error:error});
    }
}

const fetchClockedInDesignOrderStaffTaskTimelog = async (req, reply) => {
    try{
        const {userId, projectId, taskId, isDriver, instIds} = req.body;
        const result = await Request.fetchClockedInDesignOrderStaffTaskTimelog(userId, projectId, taskId);
        if(result){
            reply.send({status:1, message:"Timelog fetched successfully",result:result})
        }else{
            reply.send({status:0, message:"No open timelog found"})
        }
    }catch(error){
        console.log("Error fetching staff task timelog : ",error);
        reply.send({status:500, message:"Error fetching timelog",error:error})
    }
}

const updateDesignOrderStaffTaskTimelog = async (req, reply) => {
    try{
        const {checkedItems, taskId, projectId, checkedInstallations, userId, timeLogId, now, startTime, staffId, staffHourlyRate, memberClockins, isDriver} = req.body
        let notificationMsg=''
        let projectTaskDetails='';
        let requestServices='';
        let stafftimelogs='';
        let newhours = 0;
        let newhours1 = 0;
        let hours = 0;
        let laborInstallId = 10;
        let currentDate = Math.round(moment().valueOf() / 1000);
        let insertedstatus = false;
        let newhoursTotal = 0;

        // Handle new memberClockins format
        if (memberClockins && Array.isArray(memberClockins) && memberClockins.length > 0) {
            console.log('📌 Processing memberClockins for design order:', memberClockins);
            
            for (const item of memberClockins) {
                const {
                    staff_id,
                    hour,
                    service_id,
                    subtask_id,
                    start_time,
                    end_time,
                    hourly_rate,
                    userId: staffUserId,
                    user_id,
                    staff_name,
                    subtask_name
                } = item;

                const elapsedTimeSeconds = end_time - start_time;
                const elapsedTimeHours = elapsedTimeSeconds / 3600;
                const totalAmount = parseFloat((hourly_rate || 0) * elapsedTimeHours).toFixed(2);

                console.log(`⏱️ Processing staff ID ${staff_id} - Hours: ${hour}, Amount: ${totalAmount}`);

                const timeLogData = {
                    design_order_id: projectId,
                    task_id: taskId,
                    sub_task_id: subtask_id,
                    user_id: user_id || staffUserId,
                    start_time,
                    end_time,
                    status: 1,
                    noSubTask: 0
                };
                const timeLogId = await Request.addDesignOrderStaffTaskTimelog(timeLogData);
                console.log('🧾 Created design order timelog ID:', timeLogId);

                if (timeLogId) {
                    const payoutData = {
                        design_order_id: projectId,
                        task_id: taskId,
                        log_id: checkedItems?.join(',') || subtask_id || null,
                        timelog_id: timeLogId,
                        team: staff_id,
                        paid_at: end_time,
                        amount: totalAmount,
                        timestamp: moment().unix(),
                        is_time_tracking: 1,
                        added_by: userId,
                        status: 1,
                        is_auto_pay: 1
                    };
                    await Request.addDesignOrderPayOut(payoutData);
                    newhoursTotal += parseFloat(hour);
                    insertedstatus = true;
                }
            }

            // Get userType from users table to validate
            const userData = await Admin.getUserById(userId);
            const actualUserType = userData && userData[0] ? userData[0].user_type : null;
            
            // Check if userType is 11 and update design_order_job_status if needed
            if(actualUserType === 11 && projectId){
                const fundDesignOrderById = await Request.getDesignOrderByIdNew(projectId)
                const designOrder = fundDesignOrderById[0];
                let currentJobStatus = designOrder?.dataValues?.design_order_job_status;

                if(currentJobStatus === 1 || currentJobStatus === 3 || currentJobStatus === 4){
                    const updateData = {
                        design_order_job_status: 2,
                        working_designer_id: userId
                    }
                    await Request.updateDesignOrders(projectId, updateData);
                    console.log('Updated design_order_job_status from 1 to 2 for userType 11 in updateDesignOrderStaffTaskTimelog');
                }
            }

            if (insertedstatus) {
                if(taskId){
                    projectTaskDetails = await Request.getDesignOrderProjectTaskById(taskId);
                    
                    if(projectTaskDetails?.length > 0){
                        projectTaskDetails = projectTaskDetails[0];
                        stafftimelogs = await Request.fetchDesignOrderStaffTaskTimelog( false, false, taskId, false, false );
                        
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray = subData?.sub_task_id ? subData?.sub_task_id.split(",") : [];
                                for (const sub of subTaskArray) {
                                    if (parseInt(subData.task_id) == taskId) {
                                        const startMoment = moment.unix(subData.start_time);
                                        let endMoment;
                                        if (subData.end_time !== null) {
                                            endMoment = moment.unix(subData.end_time);
                                        } else {
                                            endMoment = moment();
                                        }
                                        const duration = moment.duration(endMoment.diff(startMoment));
                                        hours = duration.asHours();
                                        subData['hours'] = hours
                                        if (!isNaN(hours)) {
                                            newhours += hours;
                                        }
                                    }
                                }
                            }
                        }

                        requestServices = await Request.getDesignOrderServicesByDesignOrder(projectTaskDetails.design_order_id);
                        console.log('requestServices',requestServices)
                        console.log('projectTaskDetails',projectTaskDetails)
                        for(const item of requestServices){
                            if(projectTaskDetails.labour_cost_service_id == item.labour_cost_service_id){
                                let payoutData = await Request.getDesignOrderPayOutByTaskId(taskId);
                                console.log("payoutData",payoutData)
                                if(payoutData && payoutData?.length > 0){
                                    let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
                                    console.log("totalPayoutAmount",totalPayoutAmount)

                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_unit_cost : memberClockins[0]?.hourly_rate || 0,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : 1
                                    }
                                    let updateRequestServices = await Request.updateDesignOrderService(data,item.id)
                                }
                            }
                        }
                    }
                }

                if(checkedItems?.length > 0){
                    for(const data of checkedItems){
                        let updateData = {}
                        updateData['status'] = 0
                        await Request.updateDesignOrderLogStatus(updateData, data)
                    }
                }
                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);

                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);
                    }
                }
            }
            let oldHours = newhours
            let oldHours1 = newhours1
            newhours = formatHoursToHHMMSS(newhours);
            newhours1 = formatHoursToHHMMSS(newhours1);
            reply.send({ status:1, message:"Task Timelog updated successfully",result:'update',newhours1,oldHours1,
                notificationMsg:notificationMsg, projectTaskDetails,requestServices,stafftimelogs, newhours, oldHours })
            return;
        }

        // Old format handling (backward compatibility)
        const elapsedTimeSeconds = now - startTime;
        const elapsedTimeHours = elapsedTimeSeconds / 3600;
        console.log('elapsedTimeHourselapsedTimeHours--startTime',startTime)
        console.log('elapsedTimeHourselapsedTimeHours--now',now)
        console.log('elapsedTimeHourselapsedTimeHours--elapsedTimeHours',elapsedTimeHours)
        const totalAmount = (staffHourlyRate || 0) * elapsedTimeHours;
        const finalAmount = totalAmount * (checkedItems.length || 1)
        let data = {}
        data.end_time = now ? now : currentDate
        const newUserId =  userId
        const updateResult = await Request.updateDesignOrderStaffTaskTimelog(data, taskId, projectId, checkedInstallations, newUserId, timeLogId);
        if(updateResult){
            // Get userType from users table to validate
            const userData = await Admin.getUserById(userId);
            const actualUserType = userData && userData[0] ? userData[0].user_type : null;
            
            // Check if userType is 11 and update design_order_job_status if needed
            if(actualUserType === 11 && projectId){
                const fundDesignOrderById = await Request.getDesignOrderByIdNew(projectId)
                const designOrder = fundDesignOrderById[0];
                let currentJobStatus = designOrder?.dataValues?.design_order_job_status;

                // Check if current design_order_job_status is 1, 3, or 4
                if(currentJobStatus === 1 || currentJobStatus === 3 || currentJobStatus === 4){
                    const updateData = {
                        design_order_job_status: 2,
                        working_designer_id: userId
                    }
                    await Request.updateDesignOrders(projectId, updateData);
                    console.log('Updated design_order_job_status from 1 to 2 for userType 11 in updateDesignOrderStaffTaskTimelog');
                }
            }
            let data = {
                design_order_id: projectId || null,
                task_id: taskId || null,
                log_id: checkedItems?.join(',') || null,
                timelog_id: timeLogId || null,
                team: userId,
                paid_at: now,
                // amount: totalAmount,
                amount: finalAmount,
                timestamp: moment().unix(),
                is_time_tracking: 1,
                added_by: userId,
                status:1,
                is_auto_pay:1
            };
            insertedstatus = await Request.addDesignOrderPayOut(data)
            if (insertedstatus) {
                if(taskId){
                projectTaskDetails = await Request.getDesignOrderProjectTaskById(taskId);
                
                if(projectTaskDetails?.length > 0){
                    projectTaskDetails = projectTaskDetails[0];
                    // if(projectTaskDetails['job_category_name'] == 'Time & Material'){
                        stafftimelogs = await Request.fetchDesignOrderStaffTaskTimelog( false, false, taskId, false, false );
                        
                        if (stafftimelogs && stafftimelogs?.length > 0) {
                            for (const subData of stafftimelogs) {
                                let subTaskArray =subData?.sub_task_id? subData?.sub_task_id.split(",") : [];
                                for (const sub of subTaskArray) {
                                if (parseInt(subData.task_id) == taskId) {
                                    const startMoment = moment.unix(subData.start_time);
                                    let endMoment;
                                    if (subData.end_time !== null) {
                                        endMoment = moment.unix(subData.end_time);
                                    } else {
                                        endMoment = moment();
                                    }
                                    const duration = moment.duration(endMoment.diff(startMoment));
                                    hours = duration.asHours();
                                    subData['hours'] = hours
                                    if (!isNaN(hours)) {
                                        newhours += hours;
                                    }
                                }
                                }
                            }
                        }
                        // const calculatedHours = formatHoursToHHMMSS(newhours);
                        // reply.send({newhours,hours,calculatedHours,stafftimelogs})

                        requestServices = await Request.getDesignOrderServicesByDesignOrder(projectTaskDetails.design_order_id);
                       console.log('requestServices',requestServices)
                       console.log('projectTaskDetails',projectTaskDetails)
                        for(const item of requestServices){
                            if(projectTaskDetails.labour_cost_service_id == item.labour_cost_service_id){
                                let payoutData = await Request.getDesignOrderPayOutByTaskId(taskId);
                                console.log("payoutData",payoutData)
                                if(payoutData && payoutData?.length > 0){
                                    let totalPayoutAmount = payoutData?.reduce((total, item) => total + (item.amount || 0), 0);
                                      console.log("totalPayoutAmount",totalPayoutAmount)

                                    let data = {
                                        jobcost_quantity : newhours,
                                        jobcost_unit_cost : staffHourlyRate || 0,
                                        jobcost_total_cost : totalPayoutAmount,
                                        taken : 1
                                        // taken : newhours >= item.quantity ? 1 :0 
                                    }
                                    let updateRequestServices = await Request.updateDesignOrderService(data,item.id)
                               
                                }
                            }
                        }
                    // }
                }}

                if(checkedItems?.length > 0){
                    for(const data of checkedItems){
                        let updateData = {}
                        updateData['status'] = 0
                        await Request.updateDesignOrderLogStatus(updateData, data)
                    }
                }
                notificationMsg = `New Pay Out has been added`;
                let notificationUrl = "staff-payout";
                const incrementResult_User = await Admin.incrementField(userId,"noti_count",1);

                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);
                    }
                }
            }
            let oldHours = newhours
            let oldHours1 = newhours1
            newhours = formatHoursToHHMMSS(newhours);
            newhours1 = formatHoursToHHMMSS(newhours1);
            reply.send({ status:1, message:"Task Timelog updated successfully",result:'update',newhours1,oldHours1,
                notificationMsg:notificationMsg, projectTaskDetails,requestServices,stafftimelogs, newhours, oldHours })
        }else{
            reply.send({status:0, message:"Failed to update timelog"})
        }
    }catch(error){
        console.log("Update design order staff task timelog error : ",error);
        reply.send({status:0, message:"Failed to update timelog", error: error.message})
    }
}

const uploadReceiptToQuickbook = async(req,res)=>{
    try {
        const {receipt} = req.body
       await sendReceiptEmail(receipt)
        res.send({status:1,message:"success"})
    } catch (error) {
        console.log("error",error)
        res.send({status:500, message:"Error fetching timelog",error:error})
    }
}

module.exports = {
    updatateProjectStatus, updatateJobHoldStatus, addProjectTask, updateProjectTask, updatateProjectTaskStatus,
    updateTaskWorkflowByOrderProduct,
    addProjectSubTask, viewSubTask, updateProjectSubTask, deleteProjectTask, deleteProjectSubTask,
    deleteDesignOrderProjectTask,
    deleteDesignOrderProjectTaskMember,
    deleteDesignOrderProjectSubTask,
    deleteProjectTaskMember,updatateProjectSubTaskStatus,addProjectTaskAttachments,
    fetchProjectTaskAttachments,deleteProjectTaskAttachments,addProjectAttachments,
    fetchProjectAttachments,deleteProjectAttachments,addStaffTaskTimelog, updateStaffTaskTimelog, 
    fetchStaffTaskTimelog, fetchClockedInStaffTaskTimelog, fetchAllStaffTaskTimelog,
    addTimesheet, addManualStaffTaskTimelog, deleteManualStaffTaskTimelog, addDesignOrderAttachments,
    fetchDesignOrderAttachments,deleteDesignOrderAttachments,viewDesignOrderSubTask,
    updatateDesignOrderProjectSubTaskStatus, updatateDesignOrderJobHoldStatus,addDesignOrderStaffTaskTimelog,
    fetchClockedInDesignOrderStaffTaskTimelog,updateDesignOrderStaffTaskTimelog,approveManualStaffTaskTimelog,
    uploadReceiptToQuickbook,fetchAllProjectAttachments,checkReadyForInstallationStatus,
    checkAllProjectTasksCompletedStatus,addStaffTaskTimelogDriverAndInstaller,updateStaffTaskTimelogDriverAndInstaller,handleDesignOrderTimelogPayout,
    deleteManualStaffDesignTaskTimelog,approveDesignManualStaffTaskTimelog,addInstallerTaskTimelog,updateInstallerTaskTimelog,
}