const sequelize = require("../config/dbconnection");
const Teams = require("../models/teams");
const client = require("../models/client");
const Contact = require("../models/contacts");
const Admin = require("../models/admin");
const moment = require("moment");
const crypto = require('crypto')
const Ticket = require("../models/tickets");
const TaskMessage = require("../models/taskMessages");
const TaskMember = require("../models/taskMember");
const UerLogAction = require("../models/userLogAction");
const Password = require("node-php-password");
const { empty, arrayColumn } = require("../Helpers/Common");

const { inviteLinkTemplate } = require("../libraries/emailTemplates");
const { MAIL_SENDER, SEND_EMAIL, DOMAIN } = require("../constants/constant");
const { baseUrl } = require("../constants/constant");
// const { transporter } = require("../constants/common");
const sgMail = require('@sendgrid/mail')
const { SENDGRID_API_KEY, BASE_URL, portalName } = require("../constants/constant")
const nodemailer = require('nodemailer');

const TICKET_PREFIX = (DOMAIN == 'arizona') ? 'AZ-' : (DOMAIN == 'riv') ? 'RIV-' : (DOMAIN == 'la') ? 'LA-' : (DOMAIN == 'nca') ? 'NCA-' : 'SW-'

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


const { sendPartnerMail, rfqEmail } = require("../constants/emailTemplates");
let currentTime = moment().unix();

const Project = require("../models/Projects");
const { CURRENT_INSTALLATION, FACILITY_ID } = require("../config/SplitManagementDb");
const getAllTickets = async (req, res) => {
  try {

    let { 
      permission, 
      userId, 
      userType,
      page = 1,
      limit = 10,
      search = '',
      status = null,
      module = null,
      priority = null,
      ticket_type = null,
      dateRange = null
    } = req.body;
    
    // Assuming Admin.isPrivileged returns a promise
    let userPermission = await Admin.isPrivileged(permission);

    let exploded_permissions = [];
    if (!empty(userPermission)) {
      exploded_permissions = arrayColumn(userPermission, "previleges");
    }

    // Calculate offset for pagination
    const offset = (page - 1) * limit;

    // Build filter object
    const filters = {
      search: search || '',
      status: status !== null && status !== undefined ? status : null,
      module: module || null,
      priority: priority || null,
      ticket_type: ticket_type || null,
      dateRange: dateRange || null
    };

    let data = {};
    data["exploded_permissions"] = exploded_permissions;
    
    let result;
    if (userType === 1) {
      result = await Ticket.getAllTasks(0, userType, null, limit, offset, filters);
    } else if (userType == 3) {
      let clientDetails = await client.getPartnerByUserId(userId)
      result = await Ticket.getAllTasks(clientDetails.id, userType, null, limit, offset, filters);
    } else {
      result = await Ticket.getAllTasks(0, userType, userId, limit, offset, filters);
    }

    data["task"] = result.tasks || [];
    data["totalCount"] = result.totalCount || 0;

    // Get status counts (excluding status filter)
    const statusFilters = { ...filters };
    delete statusFilters.status; // Remove status filter to get counts for all statuses
    let statusCountsResult;
    if (userType === 1) {
      statusCountsResult = await Ticket.getStatusCounts(0, userType, null, statusFilters);
    } else if (userType == 3) {
      let clientDetails = await client.getPartnerByUserId(userId)
      statusCountsResult = await Ticket.getStatusCounts(clientDetails.id, userType, null, statusFilters);
    } else {
      statusCountsResult = await Ticket.getStatusCounts(0, userType, userId, statusFilters);
    }
    data["statusCounts"] = statusCountsResult.statusCounts || {};
    data["totalCountAll"] = statusCountsResult.totalCount || 0;

    // Include taskMembers for each task
    if (data["task"] && data["task"].length > 0) {
      for (let task of data["task"]) {
        let taskId = task.ID; // Assuming each task object has an `id` field
        task["taskMembers"] = await Ticket.getTaskMembers(taskId);
      }
    }

    res.send({
      message: "Fetched all tickets",
      data,
    });
  } catch (error) {
    console.error(error); // Use console.error for logging errors
    res.status(500).send({
      message: "Internal server error",
      error: error.message, // Send error message to the client
    });
  }
};
const getTicketsByUserId = async (req, res) => {
  try {
    let { tasksource, userId } = req.body;

    let fieldName = "";
    if (tasksource == 1) {
      fieldName = "partner_id";
    } else if (tasksource == 2) {
      fieldName = "contact_id";
    } else if (tasksource == 3) {
      fieldName = "lead_id";
    }
    if (!empty(tasksource)) {
      let tickets = await Ticket.getUserAssignedTasks(fieldName, userId);

      if (!empty(tickets)) {
        res.send({
          status: 1,
          tickets,
          msg: "fetched successfully",
        });
      } else {
        res.send({
          status: 0,
          msg: "failed to fetch tickets",
        });
      }
    }
  } catch (error) {
    console.log(error);
  }
};
// const addTickets = async (req, reply) => {
//   try {
//     let { values, taskSource, userId, userType, sourceId } = req.body;
//     let ticket_url = "";
//     let ticketResult = [];
//     if (!empty(taskSource)) {
//       if (taskSource == 1) {
//         ticket_url = `${BASE_URL}admin/partner/view/${sourceId}/0/${taskSource}`;
//         if (userType == 3) {
//           ticket_url = `${BASE_URL}admin/partner/profile`;
//         }
//         let ticketResult = await client.getClientById(sourceId);
//       } else if (taskSource == 2) {
//         ticket_url = `${BASE_URL}admin/contact/view-contact/${sourceId}/0/${taskSource}`;
//         let ticketResult = await Contact.getContactById(sourceId);
//       } else if (taskSource == 3) {
//         ticket_url = `${BASE_URL}admin/lead/view-lead/${sourceId}/0/${taskSource}`;
//         let ticketResult = await client.getClientById(sourceId);
//         // here there will be lead model
//       }
//     } else {
//       ticket_url = BASE_URL + "admin/tasks";
//     }
//     let ticketData = {};

//     if (!empty(values)) {
//       ticketData["name"] = values.name;
//       ticketData["description"] = values.description;
//       ticketData["project_id"] = values?.projects?.id;
//       ticketData["status"] = 1
//       ticketData["ticket_uid"] = await Ticket.getTicketId(values?.projects?.id);
//       ticketData["complete"] = values.complete || 0;
//       ticketData["userid"] = userId;
//       ticketData['timestamp'] = moment().unix()
//       if(!empty(values.cover)){
//         ticketData['ticket_file'] = values.cover
//       }
//       ticketData['priority'] = values.priority.id
//       let clientDetails ={}
//       if(userType===3){
//        clientDetails = await client.getPartnerByUserId(userId)
//         ticketData['partner_id'] = clientDetails.id
//       }else{
//         clientDetails = await client.getClientById(values.client?.id)
//         ticketData['partner_id'] = values?.client?.id
//       }
//       if (!empty(taskSource)) {
//         if (taskSource == 1) {
//           ticketData["partner_id"] = sourceId;
//           ticketData["contact_id"] = 0;
//           ticketData["lead_id"] = 0;
//         } else if (taskSource == 2) {
//           ticketData["partner_id"] = 0;
//           ticketData["contact_id"] = sourceId;
//           ticketData["lead_id"] = 0;
//         } else {
//           ticketData["partner_id"] = 0;
//           ticketData["contact_id"] = 0;
//           ticketData["lead_id"] = sourceId;
//         }
//       }

//       let ticketId = await Ticket.AddTickets(ticketData);

//       if (!empty(ticketId)) {

//         let currentTicket = await Ticket.getTask(ticketId);
//         let virtualTicketNumber =
//           currentTicket["short_code"] + "SW" + currentTicket["ticket_uid"];
//         // have a doubt below
//         // 	$virtual_ticket_number=$current_task['short_code'].sprintf('%04d',$current_task['ticket_uid']);
//         if (values.addToJobTeam) {
//           await TaskMember.addtaskMember({ taskid: ticketId, userid: userId });

//           //notification
//           let incrementResult = await Admin.incrementField(
//             userId,
//             "noti_count",
//             1
//           );
//           let addNotification = {
//             user_id: userId,
//             url: "tasks",
//             timestamp: currentTime,
//             message: `A new task ${values.name} has been added to you`,
//             status: 1,
//             from_id: userId,
//           };
//         }
//         let welcome = `Hello ${clientDetails.first_name},`
//         let subject = 'Support Ticket';
//         let email_content = `New Ticket : ${ ticketData["name"]}  has been raised ` ;
//         let message = rfqEmail()
//         message = message.replace('[emailContent]', email_content)
//         message = message.replace('[CONTENT]', welcome)

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

//         const mailOptions = {
//           to:  clientDetails.email , 
//           from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
//           subject: subject,
//           text: subject,
//           html: message,
//         }
//         try {
//           await transporter.sendMail(mailOptions);
//           console.log('Email sent');

//         } catch (error) {
//           console.error('##########Err', error);

//         }
//           welcome = "Hello Admin,"
//           email_content=`New Ticket : ${ ticketData["name"]}  has been raised  by ${clientDetails.first_name}`
//           subject=" A new Job has been assigned "
//           message = rfqEmail()
//           message = message.replace('[emailContent]', email_content)
//           message = message.replace('[CONTENT]', welcome)

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

//             const mailOptions = {
//               to:  row , 
//               from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
//               subject: subject,
//               text: subject,
//               html: message,
//             }
//             try {
//               await transporter.sendMail(mailOptions);
//               console.log('Email sent');

//             } catch (error) {
//               console.error('##########Err', error);

//             }
//           }

//         reply.send({
//           status: 1,
//           message: "A new Support ticket" + values.name + " has been added",
//         });
//       }
//       reply.send({ status: 1, message: "Failed to add  new Support ticket" });
//     }
//     reply.send({ status: 1, message: "Failed to add  new Support ticket" });
//   } catch (error) {
//     console.log("Server error" + error);
//   }
// };



const addTickets = async (req, reply) => {
  try {
    let { values, taskSource, userId, userType, sourceId, admin_mail, avatarUrl, date, created_from_installation_id } = req.body;




    let ticket_url = "";
    let ticketResult = [];
    if (!empty(taskSource)) {
      if (taskSource == 1) {
        ticket_url = `${BASE_URL}admin/partner/view/${sourceId}/0/${taskSource}`;
        if (userType == 3) {
          ticket_url = `${BASE_URL}admin/partner/profile`;
        }
        let ticketResult = await client.getClientById(sourceId);
      } else if (taskSource == 2) {
        ticket_url = `${BASE_URL}admin/contact/view-contact/${sourceId}/0/${taskSource}`;
        let ticketResult = await Contact.getContactById(sourceId);
      } else if (taskSource == 3) {
        ticket_url = `${BASE_URL}admin/lead/view-lead/${sourceId}/0/${taskSource}`;
        let ticketResult = await client.getClientById(sourceId);
        // here there will be lead model
      }
    } else {
      ticket_url = BASE_URL + "admin/tasks";
    }
    let ticketData = {};

    if (!empty(values)) {
      ticketData["name"] = values.name;
      ticketData["description"] = values.description;
      ticketData["status"] = values?.priority?.id == 4 ? 16 : 1;
      if (values?.projects?.id) {

        ticketData["project_id"] = values?.projects?.id;
        ticketData["ticket_uid"] = await Ticket.getTicketId(values?.projects?.id);
      }
      ticketData["complete"] = values.complete || 0;
      ticketData["userid"] = userId;
      ticketData["module"] = values?.module?.id || null;
      ticketData['timestamp'] = moment().unix()
      ticketData['due_date'] = date.due_date
      ticketData['status_updated'] = moment().unix()
      ticketData['created_from_installation_id'] = created_from_installation_id == 0 ? 0 : null
      if (!empty(values.cover)) {
        ticketData['ticket_file'] = values.cover
      }
      ticketData['priority'] = values.priority.id
      ticketData['ticket_type'] = values.ticket_type.id
      let clientDetails = {}


      let ticketId = await Ticket.AddTickets(ticketData);

      if (!empty(ticketId)) {

        if (Array.isArray(avatarUrl) && avatarUrl.length > 0) {
          let time = moment().unix();

          for (const file of avatarUrl) {
            const fileData = {
              userid: userId || 1,
              taskid: ticketId,
              extension: file.extension,
              file_size: file.size || 1,
              file_type: file.file_type,
              file_url: file.url,
              timestamp: time,
              upload_file_name: values?.name,
            };

            try {
              let AddFile = await Ticket.AddFilesToTask(fileData);
              console.log(`File ${file.url} added successfully.`);
            } catch (error) {
              console.error(`Error adding file ${file.url}:`, error);
            }
          }
        } else {
          console.error("avatarUrl is not a valid array or is empty.");
        }


        if (Array.isArray(values?.agent) && values.agent.length > 0) {
          for (const agent of values.agent) {
            const uid = agent.id ?? agent.member_id;
            if (uid == null) continue;
            let memberData = {
              taskid: ticketId,
              userid: uid,
            };
            let insertedId = TaskMember.addtaskMember(memberData);
          }
        } else if (values?.agent && (values.agent.id != null || values.agent.member_id != null)) {
          const uid = values.agent.id ?? values.agent.member_id;
          let memberData = {
            taskid: ticketId,
            userid: uid,
          };
          let insertedId = TaskMember.addtaskMember(memberData);
        }

        let currentTicket = await Ticket.getTask(ticketId);
        let virtualTicketNumber =
          currentTicket["short_code"] + "SW" + currentTicket["ticket_uid"];
        // have a doubt below
        // 	$virtual_ticket_number=$current_task['short_code'].sprintf('%04d',$current_task['ticket_uid']);
        if (values.addToJobTeam) {
          await TaskMember.addtaskMember({ taskid: ticketId, userid: userId });

          //notification
          let incrementResult = await Admin.incrementField(
            userId,
            "noti_count",
            1
          );

        }


        let currentTime = moment().unix();

        let addNotification = {
          user_id: userId,
          url: "tasks",
          timestamp: currentTime,
          // message: `A new task ${values.name} has been added to ${values?.agent?.name},module ${values?.module?.module_name}, priority :${values?.priority?.value}`,
          message: `A new task ${values.name} has been added to ${values?.agent?.name || "support agent"}${values?.module?.module_name ? `, module: ${values.module.module_name}` : ""}, priority: ${values?.priority?.value || "Low"}, ticket type: ${values?.ticket_type?.value || 'Bug'}`,
          status: 1,
          from_id: userId,
        };

        await Admin.addNotification(addNotification)



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

        // message = message.replace('[LOGIN_URL]', `${BASE_URL}`)
        // const msg = {
        //   to: clientDetails.email, 
        //   from: 'nushara@skyniche.com', 
        //   subject: subject,
        //   text: subject,
        //   html: message,
        // }
        // sgMail
        //   .send(msg)
        //   .then(() => {
        //     console.log('Email sent')
        //   })
        //   .catch((error) => {
        //     console.error(error)
        //   })
        let subject = 'Support Ticket';
        let message = `
        <p>Dear Admin,</p>
        <p>Welcome! We are pleased to inform you that a new task has been added.</p>
        <p>A new task <strong>${values.name}</strong> has been added to <strong>${values?.agent?.name}</strong>.</p>
        <p>Priority: <strong>${values?.priority?.value}</strong></p>
        <p>Ticket Type: <strong>${values?.ticket_type?.value}</strong></p>
        <p>Module: <strong>${values?.module?.module_name}</strong></p>
      `;

        const mailOptions = {
          to: admin_mail,
          from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
          subject: subject,
          text: subject,
          html: message,
        }
        try {
          if (SEND_EMAIL) {
            await transporter.sendMail(mailOptions);
            console.log('Email sent', admin_mail);
          }
        } catch (error) {
          console.error('##########Err', error);

        }

        let TeamMessage = `
        <p>Dear Team Member,</p>
        <p>Welcome! A new task has been assigned to you.</p>
        <p>A new task <strong>${values.name}</strong> has been added to <strong>you</strong>.</p>
        <p>Priority: <strong>${values?.priority?.value}</strong></p>
        <p>Ticket Type: <strong>${values?.ticket_type?.value}</strong></p>
        <p>Module: <strong>${values?.module?.module_name}</strong></p>
      `;

        const mailOptions2 = {
          to: values?.agent?.email,
          from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
          subject: subject,
          text: subject,
          html: TeamMessage,
        }
        try {
          if (SEND_EMAIL) {
            await transporter.sendMail(mailOptions2);
            console.log('Email sent');
          }
        } catch (error) {
          console.error('##########Err', error);

        }

        // welcome = "Hello Admin,"
        // email_content=`New Ticket : ${ ticketData["name"]}  has been raised  by ${clientDetails.first_name}`
        // subject=" A new Job has been assigned "
        // message = rfqEmail()
        // message = message.replace('[emailContent]', email_content)
        // message = message.replace('[CONTENT]', welcome)

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

        //   const mailOptions = {
        //     to:  row , 
        //     from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
        //     subject: subject,
        //     text: subject,
        //     html: message,
        //   }
        //   try {
        //     await transporter.sendMail(mailOptions);
        //     console.log('Email sent');

        //   } catch (error) {
        //     console.error('##########Err', error);

        //   }
        // }

        reply.send({
          status: 1,
          message: "A new Support ticket " + values.name + " has been added",
        });
      }
      reply.send({ status: 1, message: "Failed to add  new Support ticket" });
    }
    reply.send({ status: 1, message: "Failed to add  new Support ticket" });
  } catch (error) {
    console.log("Server error" + error);
  }
};



const deleteMessageinTickets = async (req, res) => {
  try {
    let { taskId, id } = req.body;
    let task = await Ticket.getAllTasks(taskId);
    let deleted = await Ticket.deleteMessages(id);
    //notification
    let notifytaskMember = {
      taskId,
      message: `A message has been deleted in a Task that you are assigned to:<strong>. ${task["name"]} </strong>`,
      userId,
    };

    let userLog = {
      user_id: userId,
      url: `tasks/view/"${taskId}`,
      timestamp: currentTime,
      message: `deleted a message to task: ${task["name"]}`,
      status: 1,
      //   "IP" => $_SERVER['REMOTE_ADDR'],
      taskid: taskId,
    };
    await UerLogAction.addUserLog(userLog);
  } catch (error) {
    console.log(error);
  }
};
const viewActivity = async (req, res) => {
  try {
    let { taskId } = req.body;
    let taskResult = await Ticket.getTask(taskId);
    let taskActivity = await Ticket.getTaskActivity(id, (limit = 0));
    res.send({
      status: 1,
      taskActivity,
      taskResult,
    });
  } catch (error) {
    console.log(error);
  }
};
const addMessage = async (req, res) => {
  try {
    let { taskId, message, userId, sent_from_installation_id } = req.body;

    let taskResult = await Ticket.getTask(taskId);
    if (!empty(message)) {
      let messageData = {
        userid: userId,
        message: message,
        timestamp: moment().unix(),
        taskid: taskId,
        sent_from_installation_id: sent_from_installation_id ? 0 : null,
      };

      await TaskMessage.addMessages(messageData);
      //log
      // let logdata = {
      //   userid: userId,
      //   message: `posted a new message to task ${taskResult["name"]}`,
      //   timestamp: currentTime,
      //   taskid: taskId,
      // };
      // await UerLogAction.addUserLog(logdata);
      // await notifytaskMember(
      //   taskId,
      //   `A new message has been posted in a Task that you are assigned to: <strong>".${taskResult["name"]}.</strong>`,
      //   userId
      // );

      res.send({
        status: 1,
        message: "The message was posted!",
      });
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error);
  }
};
const deleteMessage = async (req, res) => {
  try {
    let { messageId, userId, } = req.body;

    let taskResult = await Ticket.deleteMessages(messageId);
    if (taskResult) {


      res.send({
        status: 1,
        message: "The message was deleted !",
      });
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error);
  }
};



const addtaskMembers = async (req, res) => {
  try {
    let { taskId, selectedTeam, admin_mail, user_type, task } = req.body;
    let currentTime = moment().unix();


    let taskResult = await Ticket.getTask(taskId);

    let addNotification = {
      user_id: 1,
      url: "tasks",
      timestamp: currentTime,
      // message: `A new task ${task.name} has been added ${task?.module_name ? `module`+task?.module_name : ''}, priority :${task?.priority ==1? "High":task?.priority ==2? "Medium" :"Low"}`,
      message: `A new task ${task.name} has been added${task?.module_name ? ` to module ${task.module_name}` : ''}, priority: ${task?.priority === 1 ? "High" : task?.priority === 2 ? "Medium" : "Low"}`,
      status: 1,
      from_id: 1,
    };

    await Admin.addNotification(addNotification)

    for (let eachUserId of selectedTeam) {
      let members = await TaskMember.getuserDetailById(eachUserId.id);


      //add members
      let memberData = {
        taskid: taskId,
        userid: eachUserId.id,
      };
      let insertedId = TaskMember.addtaskMember(memberData);



      let addNotification = {
        user_id: members.id,
        url: "tasks",
        timestamp: currentTime,
        // message: `A new task ${task.name} has been added to you,module ${task?.module_name}, priority :${task?.priority ==1? "High":task?.priority ==2? "Medium" :"Low"}`,
        message: `A new task ${task.name} has been added to you,${task?.module_name ? ` module ${task.module_name}` : ''}, priority: ${task?.priority === 1 ? "High" : task?.priority === 2 ? "Medium" : "Low"}`,
        status: 1,
        from_id: members.id,
      };

      await Admin.addNotification(addNotification)

      let subject = 'Support Ticket';
      let TeamMessage = `
      <p>Dear Team Member,</p>
      <p>Welcome! A new task has been assigned to you.</p>
      <p>A new task <strong>${task.name}</strong> has been added to <strong>you</strong>.</p>
      <p>Priority: <strong>${task?.priority == 1 ? "High" : task?.priority == 2 ? "Medium" : "Low"}</strong></p>
      <p>Module: <strong>${task?.module_name}</strong></p>
    `;

      const mailOptions = {
        to: members.email, // "ramdharvish@skyniche.com" , 
        from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
        subject: subject,
        text: subject,
        html: TeamMessage,
      }

      try {
        if (SEND_EMAIL) {
          await transporter.sendMail(mailOptions);
          console.log('Email sent', members.email);
        }
      } catch (error) {
        console.error('##########Err', error);

      }

      if (insertedId) {
        let ticketUrl = BASE_URL + "tasks/view/" + taskResult["ID"];
        let taskSource = 0;
        // $virtual_ticket_number=$task['short_code'].sprintf('%04d',$task['ticket_uid']);
        if (!empty(taskResult["partner_id"])) {
          taskSource = 1;
        }
        if (!empty(taskResult["contact_id"])) {
          taskSource = 2;
        }
        if (!empty(taskResult["lead_id"])) {
          taskSource = 3;
        }
        if (taskSource == 1) {
          ticketUrl =
            BASE_URL +
            "admin/partner/view/" +
            taskResult["partner_id"] +
            "/0/$task_source";
        }
        if (taskSource == 2) {
          ticketUrl =
            BASE_URL +
            "admin/contact/view-contact/" +
            taskResult["contact_id"] +
            "/0/$task_source";
        }
        if (taskSource == 3) {
          ticketUrl =
            BASE_URL +
            "admin/lead/view-lead/" +
            taskResult["lead_id"] +
            "/0/$task_source";
        }


        await Admin.incrementField(eachUserId.id, "noti_count", 1);
        await Admin.addNotification({
          user_id: eachUserId.id,
          url: "tasks/view/" + taskId,
          timestamp: currentTime,
          message: "has assigned you to a task:" + taskResult["name"],
          status: 0,
          from_id: eachUserId.id,
        });
        await UerLogAction.addUserLog({
          userid: eachUserId.id,
          message:
            "added a new user <b>" + taskResult["username"] + "</b> to a task:",
          //  incomplete message    // <a href='".site_url("tasks/view/".$task['ID'])."'>".$task['name']."</a>",
          timestamp: currentTime,
          //  "IP" => $_SERVER['REMOTE_ADDR'],
          url: `tasks/view/${taskResult["ID"]}`,
          taskid: taskResult["ID"],
        });
        res.send({
          status: 1,
          message: "The user was added to the task!",
        });
      }
    }
  } catch (error) {
    console.log(error);
  }
};
const removeTaskMember = async (req, res) => {
  try {
    let { userId, taskId } = req.body;
    let taskResult = await Ticket.getTask(taskId);
    let taskMember = await TaskMember.getuserDetailById(userId);
    //remove member
    await TaskMember.removeTaskMember(userId, taskId);

    // Send notification of being added to the task
    await Admin.incrementField(userId, "noti_count", 1);
    await Admin.addNotification({
      userid: userId,
      url: `task/view/${taskId}`,
      timestamp: currentTime,
      status: 0,
      fromId: userId,
    });
    // Notify
    notifytaskMember(
      taskId,
      `A member ".${taskMember["username"]}." has been removed from the task \"".$task['name']."\""`,
      userId
    );
  } catch (error) {
    console.log(error);
  }
};

const notifytaskMember = async (taskId, msg, fromId) => {
  let member = await TaskMember.getTaskmembers(taskId);

  for (let eachmember of member) {
    if (eachmember.userid !== fromId) {
      await Admin.incrementField(eachmember.userid, "noti_count", 1);
      let data = {
        userid: eachmember.userid,
        url: "task",
        timestamp: currentTime,
        message: msg,
        status: 0,
        fromid: fromId,
      };
      await Admin.addNotification(data);
    }
  }
  return true;
};
const viewTicketById = async (req, reply) => {
  let taskId = req.body.taskId;
  let task = await Ticket.getTicketById(taskId);
  let taskMembers = await Ticket.getTaskMembers(taskId);
  let members = await Ticket.getUsers(taskId);
  let objectives = await Ticket.getTaskObjectives(taskId);
  // let task_sheets = await Ticket.getTaskSheets(taskId);
  // let files = await Ticket.getAttachedFiles(taskId);
  let messages = await Ticket.getTaskMessages(taskId);
  let actions = await Ticket.getActivityLog(taskId);

  if (!empty(task)) {
    reply.send({
      staus: 1,
      msg: "Ticket fetch Successfully",
      task,
      taskMembers,
      members,
      objectives,
      // files,
      messages,
      actions,
    });
  } else {
    reply.send({ staus: 0, msg: "Failed to fetch Ticket" });
  }
};
const getAllProjectsForTicket = async (req, reply) => {
  let { userId, userType } = req.body;
  let allProjects = await Project.getAllProjects(false, false, userType, userId);
  reply.send({ staus: 1, allProjects, msg: "Fetch all projects successfully" });
};
const deleteTicket = async (req, res) => {
  try {
    const { taskId, userId } = req.body;
    let task = await Ticket.getTask(taskId);
    let deleted = await Ticket.deleteTicket(taskId);
    if (deleted === true) {
      res.send({
        status: 1,
        message: `The Ticket has been deleted successfully`,
      });
    } else {
      res.send({
        status: 0,
        message: `Failed to delete the Ticket`,
      });
    }

  } catch (error) {
    console.log(error);
  }
};
const assignedTask = async (req, res) => {
  try {
    const { status, userid } = req.body;
    let data = {};
    data["tasks"] = await Ticket.getUserAssignedTasks(
      "partner_id",
      userid,
      status
    );
    if (data) {
      res.send({
        status: 1,
        data,
      });
    } else {
      return false;
    }
  } catch (error) {
    console.log(error);
  }
};
const myAssignedTask = async (req, res) => {
  try {
    const { userId, status } = req.body;
    let data = {};
    data["tasks"] = await Ticket.getUserAssignedTasks(userId, status);
    if (!empty(data)) {
      res.send({
        status: 1,
        data,
      });
    } else {
      return false;
    }
  } catch (error) {
    console.log(error);
  }
};
const myNewtasks = async (req, res) => {
  try {
    let status = 1;
    const userId = req.body;
    let data = {};
    data["tasks"] = await Ticket.getUserAssignedTasks(userId, status);
  } catch (error) {
    console.log(error);
  }
};
const fetchAllMessages = async (req, res) => {
  try {
    const { id, userId } = req.body
    let data = await Ticket.getAllicketsMessages(id)
    if (data) {
      res.send({
        status: 1, data
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error)
  }
}
const updateStatusOfTicket = async (req, res) => {
  try {
    const { status, id, userId, today } = req.body
    let ticketData = {}
    ticketData['status'] = status
    ticketData['status_updated'] = today

    const statusMap = {
      1: 'New', 2: 'In Progress', 3: 'Completed', 4: 'Re-opened', 5: 'Cancelled',
      6: 'Assigned', 7: 'Waiting for Development', 8: 'In Development', 9: 'Sent to QA for Testing',
      10: 'QA in Progress', 11: 'QA Failed', 12: 'QA Passed', 13: 'Moved to Production',
      14: 'Waiting for Client Approval', 15: 'Changes Requested', 16: 'Escalated', 17: 'On Hold',
      18: 'Client Approved', 19: 'Closed', 20: 'Client Rejected', 21: 'Need clarification', 22: 'Clarification provided'
    };
    // Get current ticket to get old status and completed_at
    let currentTicket = await Ticket.getTicketById(id);

    const COMPLETED_STATUSES = [3, 13, 5, 19, 14, 18];
    const REOPENED_STATUSES = [4, 5, 11, 15, 20, 21, 22];

    // Set completed_at only when first moving to a completed-type status (do not overwrite if already set)
    if (COMPLETED_STATUSES.includes(Number(status)) && (currentTicket?.completed_at == null || currentTicket?.completed_at === '')) {
      ticketData['completed_at'] = moment().unix();
    }
    // Set completed_at to null when reopening a ticket (do not overwrite if already set)
    if (REOPENED_STATUSES.includes(Number(status)) && (currentTicket?.completed_at !== null && currentTicket?.completed_at !== '')) {
      ticketData['completed_at'] = null;
    }

    let data = await Ticket.updateTicket(ticketData, id)
    if (data === true) {
      res.send({
        status: 1
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error)
  }
}
const updatePriorityOfTicket = async (req, res) => {
  try {
    const { priority, id, userId } = req.body
    let ticketData = {}
    ticketData['priority'] = priority
    ticketData['priority_updated'] =  moment().unix();
    let data = await Ticket.updateTicket(ticketData, id)
    if (data === true) {
      res.send({
        status: 1
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error)
  }
}
const updateTicketType = async (req, res) => {
  try {
    const { ticket_type, id, userId } = req.body;
    let ticketData = {};
    ticketData['ticket_type'] = ticket_type;
    ticketData['type_updated'] =  moment().unix();
    let data = await Ticket.updateTicket(ticketData, id);

    if (data === true) {
      res.send({
        status: 1
      });
    } else {
      res.send({
        status: 0
      });
    }
  } catch (error) {
    console.log(error);
    res.send({ status: 0, error: 'Internal Server Error' });
  }
};
const updateDevDueDateOfTicket = async (req, res) => {
  try {
    const { taskId, devDueDate, userId } = req.body
    let ticketData = {}
    ticketData['dev_due_date'] = devDueDate
    ticketData['dev_due_date_updated_by'] = userId
    let data = await Ticket.updateTicket(ticketData, taskId)
    if (data === true) {
      res.send({
        status: 1
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error)
  }
}

const updateStartDateOfTicket = async (req, res) => {
  try {
    const { taskId, startDate, userId } = req.body
    let ticketData = {}
    ticketData['start_date'] = startDate
    ticketData['start_date_updated_by'] = userId
    let data = await Ticket.updateTicket(ticketData, taskId)
    if (data === true) {
      res.send({
        status: 1
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.log(error)
  }
}

const updateDeliveryDateOfTicket = async (req, res) => {
  try {
    const { taskId, deliveryDate, userId } = req.body
    let ticketData = {}
    ticketData['delivery_date'] = deliveryDate
    ticketData['delivery_date_updated_by'] = userId
    let data = await Ticket.updateTicket(ticketData, taskId)
    if (data === true) {
      res.send({
        status: 1
      })
    } else {
      res.send({
        status: 0
      })
    }
  } catch (error) {
    console.error('Error updating delivery date:', error);
    return res.send({ status: 0, message: 'Error updating delivery date' });
  }
}

const getTeamData = async (req, res) => {
  try {
    let members = await Ticket.getTeamData();
    let Modules = await Ticket.GetAllModuleNames();

    if (members && Modules) {
      res.send({ message: 'success', status: 1, result: members, Modules })
    } else {
      res.send({ message: 'failed', status: 0, result: members })

    }

  } catch (error) {
    console.log(error)
    res.send({ message: "server error", error })
  }
}

const fetchTicketsFiles = async (req, res) => {
  try {
    const { taskId } = req.body

    const result = await Ticket.fetchFilesByTaskId(taskId)

    if (result) {
      res.send({ status: 1, result: result })
    } else {
      res.send({ status: 0 })

    }

  } catch (error) {
    console.log('error')
  }
}


const addStaffTicketTimelog = async (req, reply) => {
  try {
    const { taskId, userId, now, } = req.body


    let currentDate = Math.round(moment().valueOf() / 1000);
    let data = {}
    data.task_id = taskId || null
    data.user_id = userId
    data.team_id = userId
    data.start_time = now ? now : currentDate
    const addStaffTicketTimelog = await Ticket.AddTimeLog(data);



    if (addStaffTicketTimelog) {
      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 fetchClockedInStaffTicketTimelog = async (req, reply) => {
  try {
    const { teamId, taskId } = req.body;
    const result = await Ticket.getTimeLogByTask(taskId, teamId)

    const timeLogData = await Ticket.getAllTimeLogDataByTaskId(taskId);
    let totalTime = 0
    let newtotalTime = 0

    let details = timeLogData?.map((value) => {
      let currentDate = Math.round(moment().valueOf() / 1000);
      let detailsStartTime = Number(value.start_time)
      let detailsEndTime = Number(value.end_time)
      let startTime = detailsStartTime
      let endTime = detailsEndTime || currentDate
      let finalTime = (endTime - startTime) / 3600;
      totalTime += parseFloat(finalTime)
      newtotalTime += parseFloat(finalTime)
    })
    totalTime = formatHoursToHHMMSS(totalTime)

    if (result) {
      reply.send({ status: 1, message: "Timelog fetched successfully", timeLogData, result: result, totalTime, newtotalTime })
    } 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 updateStaffTicketTimelog = async (req, reply) => {
  try {
    const { taskId, timeLogId, now, startTime, teamId, } = req.body


    let currentDate = Math.round(moment().valueOf() / 1000);
    const elapsedTimeSeconds = now - startTime;
    const elapsedTimeHours = elapsedTimeSeconds / 3600;
    let data = {}
    data.end_time = now ? now : currentDate
    const updateResult = await Ticket.updateTimeLog(timeLogId, data);
    const timeLogData = await Ticket.getAllTimeLogDataByTaskId(taskId);
    let totalTime = 0
    let newtotalTime = 0

    let details = timeLogData?.map((value) => {

      let detailsStartTime = Number(value.start_time)
      let detailsEndTime = Number(value.end_time)

      let startTime = detailsStartTime
      let endTime = detailsEndTime
      let finalTime = (endTime - startTime) / 3600;

      totalTime += parseFloat(finalTime)
      newtotalTime += parseFloat(finalTime)
    })
    totalTime = formatHoursToHHMMSS(totalTime)
    if (updateResult) {


      // let oldHours = newhours
      // let oldHours1 = newhours1
      // newhours = formatHoursToHHMMSS(newhours);
      // newhours1 = formatHoursToHHMMSS(newhours1);
      reply.send({ status: 1, message: "Task Timelog updated successfully", result: 'update', totalTime, newtotalTime })
    } else {
      reply.send({ status: 0, message: "Failed to update timelog" })
    }
  } catch (error) {
    console.log("Update staff task timelog error : ", error);
  }
}

function formatHoursToHHMMSS(hours) {
  if (hours < 0) throw new Error("Negative hours are not supported");

  const duration = moment.duration(hours, "hours");
  const hoursPart = Math.floor(duration.asHours()); // Extract whole hours
  const minutesPart = Math.floor(duration.minutes()); // Extract whole minutes
  const secondsPart = Math.floor(duration.seconds()); // Extract whole seconds

  // Format with leading zeros
  const formattedDuration = [
    String(hoursPart).padStart(2, "0"),
    String(minutesPart).padStart(2, "0"),
    String(secondsPart).padStart(2, "0"),
  ].join(":");

  return formattedDuration;
}
const addStickyNote = async (req, res) => {
  try {
    const { sticky_note, added_by } = req.body;
    if (!sticky_note || !added_by) {
      return res.status(400).send({ status: 0, message: "Content and Added By are required" });
    }

    const stickyNoteData = {
      sticky_note,
      added_by,
      status: 1,
      timestamp: Math.floor(Date.now() / 1000),
    };

    const stickyNoteId = await Ticket.addStickyNote(stickyNoteData);

    res.send({ status: 1, message: "Sticky Note added successfully", id: stickyNoteId });
  } catch (error) {
    console.error('Error adding sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const editStickyNote = async (req, res) => {
  try {
    const { id, sticky_note, updated_by } = req.body;
    console.log('sticky_note', sticky_note)

    if (!id) {
      return res.status(400).send({ status: 0, message: "ID is required" });
    }

    const stickyNoteData = {
      sticky_note: sticky_note || null,
      updated_by: updated_by || null,
      updated_on: Math.floor(Date.now() / 1000), // ✅ set updated_on here
    };

    const result = await Ticket.editStickyNote(id, stickyNoteData);

    if (result) {
      res.send({ status: 1, message: "Sticky Note updated successfully" });
    } else {
      res.send({ status: 0, message: "Failed to update Sticky Note" });
    }
  } catch (error) {
    console.error('Error editing sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const fetchStickyNote = async (req, res) => {
  try {
    const stickyNote = await Ticket.getStickyNote();
    if (stickyNote) {
      res.send({ status: 1, data: stickyNote });
    } else {
      res.send({ status: 0, message: "No sticky note found" });
    }
  } catch (error) {
    console.error('Error fetching sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};
const addStickyNoteIndividual = async (req, res) => {
  try {
    const { sticky_note, added_by, is_private, color = null, share_with } = req.body;
    if (!sticky_note || !added_by) {
      return res.status(400).send({ status: 0, message: "Content and Added By are required" });
    }

    const stickyNoteData = {
      sticky_note,
      added_by,
      is_private: is_private ? 1 : 0,
      color,
      share_with: share_with || null,
      status: 1,
      timestamp: Math.floor(Date.now() / 1000),
    };

    const stickyNoteId = await Ticket.addStickyNoteIndividual(stickyNoteData);
    
    res.send({ status: 1, message: "Sticky Note added successfully", id: stickyNoteId });
  } catch (error) {
    console.error('Error adding sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const editStickyNoteIndividual = async (req, res) => {
  try {
    const { id, sticky_note, updated_by, is_private = false, share_with } = req.body;

    if (!id) {
      return res.status(400).send({ status: 0, message: "ID is required" });
    }

    const stickyNoteData = {
      sticky_note: sticky_note || null,
      updated_by: updated_by || null,
      is_private: is_private ? 1 : 0,
      share_with: share_with || null,
      updated_on: Math.floor(Date.now() / 1000), // ✅ set updated_on here
    };

    const result = await Ticket.editStickyNoteIndividual(id, stickyNoteData);

    if (result) {
      res.send({ status: 1, message: "Sticky Note updated successfully" });
    } else {
      res.send({ status: 0, message: "Failed to update Sticky Note" });
    }
  } catch (error) {
    console.error('Error editing sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const fetchStickyNoteIndividual = async (req, res) => {
  try {
    const { userId } = req.body
    const stickyNote = await Ticket.getStickyNoteIndividual(userId);
    if (stickyNote) {
      res.send({ status: 1, data: stickyNote });
    } else {
      res.send({ status: 0, message: "No sticky note found" });
    }
  } catch (error) {
    console.error('Error fetching sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};
const deleteNotesIndividual = async (req, res) => {
  try {
    const { id, deleted_by } = req.body;  // 🔥 Correct fields from frontend
    if (!id || !deleted_by) {
      return res.status(400).send({ status: 0, message: "Error" });
    }
    let data = {
      status: 0
    }
    const stickyNoteId = await Ticket.editStickyNoteIndividual(id, data);

    res.send({ status: 1, message: "Sticky Note added successfully", id: stickyNoteId });
  } catch (error) {
    console.error('Error deleting sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
}
const fetchAllTeamMembers = async (req, res) => {
  try {
    const { userId, userType } = req.body;  // 🔥 Correct fields from frontend    
    console.log('usersId,usersType++++++++++', req.body)
    const teamData = await Ticket.getAllTeamsForNotes(userId, userType);

    res.send({ status: 1, message: "Fetched members", teamData });
  } catch (error) {
    console.error('Error fetching members', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
}

const archiveStickyNoteIndividual = async (req, res) => {
  try {
    const { id, updated_by, archive } = req.body;

    if (!id) return res.status(400).send({ status: 0, message: "Note ID is required" });

    const updateData = {
      archive: archive === 0 ? 0 : 1, // Set archive based on input
      updated_by: updated_by || null,
      updated_on: moment().unix(),
    };

    const result = await Ticket.editStickyNoteIndividual(id, updateData);

    res.send({
      status: result ? 1 : 0,
      message: result
        ? archive === 0
          ? "Sticky note unarchived successfully"
          : "Sticky note archived successfully"
        : "Update failed",
    });
  } catch (error) {
    console.error("Archive Error:", error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const fetchArchivedStickyNotes = async (req, res) => {
  try {
    const { userId } = req.body;

    if (!userId) {
      return res.status(400).send({ status: 0, message: "User ID is required" });
    }

    const notes = await Ticket.getArchivedStickyNotes(userId); // pass userId here
    res.send({ status: 1, data: notes });
  } catch (error) {
    console.error("Fetch Error:", error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const editStickyNotePublicOrShared = async (req, res) => {
  try {
    const { id, sticky_note, updated_by, share_with } = req.body;

    if (!id || !updated_by) {
      return res.status(400).send({ status: 0, message: "ID and Updated By are required" });
    }

    // Fetch existing note if share_with is not provided
    let currentNote = {};
    if (share_with === undefined || share_with === null) {
      currentNote = await Ticket.getStickyNoteIndividualById(id); // 🛠️ You'll need to implement this if not already
    }

    const updateData = {
      sticky_note: sticky_note || null,
      updated_by,
      updated_on: Math.floor(Date.now() / 1000),
      is_private: 0,
      share_with: share_with !== undefined && share_with !== null ? share_with : currentNote.share_with
    };

    const result = await Ticket.editStickyNoteIndividual(id, updateData);

    if (result) {
      res.send({ status: 1, message: "Public/Shared Sticky Note updated successfully" });
    } else {
      res.send({ status: 0, message: "Failed to update note" });
    }
  } catch (error) {
    console.error('Error editing public/shared sticky note:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

const deleteStickyNoteForUser = async (req, res) => {
  try {
    const { note_id, user_id } = req.body;

    if (!note_id || !user_id) {
      return res.status(400).send({ status: 0, message: "note_id and user_id are required" });
    }

    const note = await Ticket.getStickyNoteIndividualById(note_id);
    if (!note) {
      return res.status(404).send({ status: 0, message: "Sticky Note not found" });
    }

    const updatedShareWith = (note.share_with || "")
      .split(',')
      .map(id => id.trim())
      .filter(id => id !== String(user_id) && id !== "") 
      .join(',');

    const result = await Ticket.editStickyNoteIndividual(note_id, {
      share_with: updatedShareWith
    });

    res.send({
      status: result ? 1 : 0,
      message: result ? "Sticky note removed for the user" : "Update failed"
    });

  } catch (error) {
    console.error('Error in deleteStickyNoteForUser:', error);
    res.status(500).send({ status: 0, message: "Server error", error: error.message });
  }
};

/**
 * Update editable ticket fields (name, description, module, start date, due date)
 * and create a user action log describing the changes.
 */
const updateTicketDetails = async (req, res) => {
  try {
    // Local ticket update
    const {
      taskId,
      userId,
      name,
      description,
      module_id,
      start_date,
      due_date,
    } = req.body;

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

    const ticket = await Ticket.getTicketById(taskId);
    if (!ticket) {
      return res.send({
        status: 0,
        message: "Ticket not found",
      });
    }

    const updateData = {};
    const changeMessages = [];

    if (typeof name === "string" && name.trim() !== "" && name !== ticket.name) {
      updateData.name = name;
      changeMessages.push(
        `updated name from "${ticket.name || ""}" to "${name}"`
      );
    }

    if (
      typeof description === "string" &&
      description.trim() !== "" &&
      description !== ticket.description
    ) {
      updateData.description = description;
      changeMessages.push(`updated description`);
    }

    if (
      module_id != null &&
      Number(module_id) !== Number(ticket.module || 0)
    ) {
      updateData.module = Number(module_id);
      changeMessages.push(
        `updated module from ID ${ticket.module ?? "N/A"} to ID ${module_id}`
      );
    }

    if (start_date != null && Number(start_date) !== Number(ticket.start_date || 0)) {
      updateData.start_date = Number(start_date);
      const oldStart =
        ticket.start_date != null
          ? moment.unix(ticket.start_date).format("MM/DD/YYYY")
          : "N/A";
      const newStart = moment.unix(Number(start_date)).format("MM/DD/YYYY");
      changeMessages.push(
        `updated start date from ${oldStart} to ${newStart}`
      );
    }

    if (due_date != null && Number(due_date) !== Number(ticket.due_date || 0)) {
      updateData.due_date = Number(due_date);
      const oldDue =
        ticket.due_date != null
          ? moment.unix(ticket.due_date).format("MM/DD/YYYY")
          : "N/A";
      const newDue = moment.unix(Number(due_date)).format("MM/DD/YYYY");
      changeMessages.push(`updated due date from ${oldDue} to ${newDue}`);
    }

    if (Object.keys(updateData).length === 0) {
      return res.send({
        status: 1,
        message: "No changes detected",
      });
    }

    const updated = await Ticket.updateTicket(updateData, taskId);
    if (!updated) {
      return res.send({
        status: 0,
        message: "Failed to update ticket",
      });
    }

    const logMessage = `Updated ticket #${taskId} (installation ${FACILITY_ID}): ${changeMessages.join(
      "; "
    )}.`;

    await UerLogAction.addUserLog({
      userid: userId,
      message: logMessage,
      timestamp: moment().unix(),
      url: `tasks/view/${taskId}`,
      taskid: taskId,
      project_id: ticket.project_id || null,
      ticket_id: `${TICKET_PREFIX}-${taskId}`,
    });

    return res.send({
      status: 1,
      message: "Ticket updated successfully",
    });
  } catch (error) {
    console.error("Error updating ticket details:", error);
    return res.send({
      status: 0,
      message: "Error updating ticket details",
    });
  }
};

module.exports = {
  getAllTickets,
  addTickets,
  deleteMessageinTickets,
  viewActivity,
  addMessage,
  deleteMessage,
  addtaskMembers,
  removeTaskMember,
  getTicketsByUserId,
  viewTicketById,
  getAllProjectsForTicket,
  deleteTicket,
  assignedTask,
  myAssignedTask,
  myNewtasks,
  fetchAllMessages,
  updateStatusOfTicket,
  updatePriorityOfTicket,
  updateTicketType,
  getTeamData,
  updateDevDueDateOfTicket,
  updateStartDateOfTicket,
  fetchTicketsFiles,
  addStaffTicketTimelog,
  fetchClockedInStaffTicketTimelog,
  updateStaffTicketTimelog,
  fetchStickyNote,
  addStickyNote,
  editStickyNote,
  fetchStickyNoteIndividual,
  addStickyNoteIndividual,
  editStickyNoteIndividual,
  deleteNotesIndividual,
  fetchAllTeamMembers,
  archiveStickyNoteIndividual,
  fetchArchivedStickyNotes,
  editStickyNotePublicOrShared,
  deleteStickyNoteForUser,
  updateDeliveryDateOfTicket,
  updateTicketDetails,
};
