
const Password = require("node-php-password");
const { JWT_SECRET, portalName, SENDGRID_API_KEY, BASE_URL, SEND_EMAIL } = require("../constants/constant")
const jwt = require("jsonwebtoken")
const Admin = require("../models/admin")
const Teams = require("../models/teams")
const Login = require('../models/login');
const { empty, generateUniquePin } = require('../Helpers/Common');
const sequelize = require('../config/dbconnection');
const moment = require('moment');
const { createTwilioSupportWorker } = require('./callCenter');
const Client = require("../models/client");
const Settings = require('../models/settings')
const { activateProfile } = require('../constants/emailTemplates');
const sgMail = require('@sendgrid/mail')
const ProjectTask = require('../models/projectTask')
const ProjectFilterPreference = require("../models/projectFilterPreference");
const nodemailer = require('nodemailer');


const transporter = nodemailer.createTransport({
  host: 'mail.signwisesolutions.com', // Replace with your domain's mail server (WHM SMTP host)
  port: 465, // 465 for secure SMTP (SSL), or 587 for TLS
  secure: true, // Use true for 465, false for other ports
  auth: {
    user: 'noreply@signwisesolutions.com', 
    pass: 'signwise@2024', 
  },
});

const login = async (req, reply) => {
  const { username, password,fcmToken  } = req.body;

  try {
    // const [results, metadata] = await sequelize.query(
    //   `
    //   SELECT u.id as user_id, u.password, u.username, u.first_name, u.last_name, u.company_name, u.user_type, u.email, 
    //   u.profile_pic, u.company_logo, u.worker_sid, u.department_id, ur.name as user_role
    //   FROM users u
    //   LEFT JOIN user_roles ur ON ur.id = u.user_type
    //   WHERE u.username = :username AND u.status = 1
    //   `,
    //   {
    //     replacements: { username },
    //     type: sequelize.QueryTypes.SELECT,
    //   }
    // );
    let results ={}
    const AllResults = await Login.userLogin(username);
    console.log("results 1",AllResults);

    
    for(const result of AllResults){
      if(await Password.verify(password, result.password)){
        results = result
        break
      }
    }
    console.log("results 2",results);
    if (results) {

      if(fcmToken){
      const letsAsignFcmToken = await Login.updateUserFCMToken(username,fcmToken)
      console.log("letsAsignFcmToken",letsAsignFcmToken)
      }
      
      const user = results;
      if (await Password.verify(password, user.password)) {
        let active = {};
        let explodedPermissions = {};
        let userData = {};
        active['active'] = 'Y';
        await Admin.updateUser(user.user_id, active);
        const token = jwt.sign({ userId: user.user_id }, JWT_SECRET, { expiresIn: 24 * 60 * 60 });
        const { password, ...userwithoutPassword } = user;
        let companyDetail = await Settings.getCompanyProfileDetails()
        let pcb_permissions = await Settings.getPCBPermission()

        userData.user_id = user['user_id'];
        userData.company_name = companyDetail[0].name;
        userData.first_name = user['name'] || user['first_name'];
        userData.username = user['username'];
        userData.last_name = user['last_name'];
        userData.person_name = `${user['first_name']} ${user['last_name']}`;
        userData.email = user['email'];
        userData.profile_pic = user['profile_pic'] != '' ? user['profile_pic'] : 'avatar.jpg';
        userData.company_logo =  companyDetail[0].company_logo 
        userData.user_type = user['user_type'];
        userData.isVendor = user['isVendor'];
        userData.driver_id = user['driver_id'];
        userData.driverId = user['driver_id'];
        userData.department_id = user['department_id'];
        userData.user_role = user['user_role'];
        userData.facebook_url = user['facebook_url']
        userData.youtube_url = user['youtube_url']
        userData.google_url = user['google_url']
        userData.linkedIn_url = user['linkedIn_url']
        userData.twitter_url = user['twitter_url']
        userData.job_title = user['job_title']
        userData.alert_status = user['alert_status']
        userData.pcb_permissions = pcb_permissions
        userData.logged_in = true;
        userData.login_time = moment().format('h:mm:ss A');
        userData.added_by_client =user['added_by_client']
        userData.parent_id =user['parent_id']
        userData.parent_user_type =user['parent_user_type']
        userData.hourly_rate =user['hourly_rate']
        userData.isClient =user['isClient']
        userData.parent_client_name =user['parent_client_name']
    
        userData.timeOut = 999999;
        console.log("user['user_permissions']", user.user_permissions);
        userData.user_permissions = user['user_permissions'] && user['user_permissions'].split(',');
        console.log("userData.user_permissions", userData.user_permissions);

        userData.last_activity = Math.round(moment().valueOf() / 1000);

        userData.token = token;
        userData.loggedAt = Math.round(moment().valueOf() / 1000);


        const privilegeResult = await Login.isPrivileged(userData.user_permissions);
        console.log("privilegeResult - ", privilegeResult);
        if (privilegeResult) {
          explodedPermissions = privilegeResult.map(entry => entry.privileges);
          console.log("explodedPermissions - ", explodedPermissions);
        }

        userData['exploded_permissions'] = explodedPermissions;

        // If user has "Administrator Access" permission, treat as admin and grant full role-1 permissions
        if (explodedPermissions && explodedPermissions.includes('Administrator Access')) {
          userData.user_type = 1;
          const adminPermissionsStr = await Login.getPermissionsForRoleId(1);
          userData['adminPermissionsStr'] = adminPermissionsStr;
          if (adminPermissionsStr) {
            const adminPermIds = adminPermissionsStr.split(',').map((id) => id.trim()).filter(Boolean);
            userData.user_permissions = adminPermIds;
            const adminPrivilegeResult = await Login.isPrivileged(adminPermIds.join(','));
            if (adminPrivilegeResult && adminPrivilegeResult.length > 0) {
              explodedPermissions = adminPrivilegeResult.map((entry) => entry.privileges);
              userData['exploded_permissions'] = explodedPermissions;
            }
          }
        }

        if (user.user_type != 3 && explodedPermissions.includes('Calls') && !user.worker_sid) {
          const workerSid = await createTwilioSupportWorker(user.user_id, `${user.first_name}_${user.last_name}`, user.department_id);
          if (workerSid) {
            userData.worker_sid = workerSid;
            await Admin.updateUser(user.user_id, { worker_sid: workerSid });
          }
        }

        if (user['user_type'] != 3 && explodedPermissions.includes('Calls') && !empty(user['worker_sid'])) {
          userData['worker_sid'] = user['worker_sid'];
        }
        let thisMonth = moment().format('MMMM');

        let theDate = moment().format('YYYY-MM-DD');
        let currentMonth = moment().format('MM');
        let weekNo = moment(theDate).add(1, 'days').week();
        let weekNum = (currentMonth === '12' && weekNo === 1) ? '52' : weekNo;

        // Get the current date/time
        let curDateTime = moment().format('YYYY-MM-DD HH:mm:ss');

      
        let data = {
          userId:user['user_id'],
          // name: user.first_name + ' ' + user.last_name,
          weekNo: weekNum,
          clockYear: moment().format('YYYY'),
          entryDate: curDateTime,
          startTime: curDateTime,
          entryType: 1,
          lastUpdated: curDateTime
        };
        console.log("###########################",data);
        let insertLog=await Login.addLog(data);
        console.log("###########################",insertLog);
        reply.send({ status: 1, user: userData, accessToken: token, message: 'Login successful' });

      } else {
        reply.code(401).send({ error: 'Invalid password' });
      }
    } else {
      reply.code(401).send({ error: 'User not found or not active' });
    }

  } catch (err) {
    console.error(err);
    reply.code(500).send({ error: 'Server error' });
  }
};
const loginWithUserId = async (req, reply) => {
  const { userType, id ,isFromClient,isFromAdmin,fromId} = req.body;

  try {
    console.log("all-dataaaaaaaaaa",req.body);
    // return
    const results = await Login.userLoginId(id);
    const parentUser = await Login.userLoginId(fromId);
    if(parentUser){
      let active = {};
      active['active'] = 'N';
      await Admin.updateUser(fromId, active);
    }

    if (results) {
      const user = results;
      if (userType===1) {
        let active = {};
        let explodedPermissions = {};
        let userData = {};
        active['active'] = 'Y';
        await Admin.updateUser(user.user_id, active);
        const token = jwt.sign({ userId: user.user_id }, JWT_SECRET, { expiresIn: 24 * 60 * 60 });
        // const { password, ...userwithoutPassword } = user;
        let companyDetail = await Settings.getCompanyProfileDetails()
        let pcb_permissions = await Settings.getPCBPermission()

        userData.user_id = user['user_id'];
        userData.team_id = user['team_id'];
        userData.client_id = user['client_id'] || user['partner_client_id'];
        userData.driver_id = user['driver_id'];
        userData.driverId = user['driver_id'];
        userData.company_name = companyDetail[0].name;
        userData.first_name = user['name'] || user['first_name'];
        userData.username = user['username'];
        userData.last_name = user['last_name'];
        userData.person_name = `${user['first_name']} ${user['last_name']}`;
        userData.email = user['email'];
        userData.profile_pic = user['profile_pic'] != '' ? user['profile_pic'] : 'avatar.jpg';
        userData.company_logo = (user['company_logo'] != '' || !user.company_logo) ? companyDetail[0].company_logo : 'default_logo.jpg';
        userData.user_type = user['user_type'];
        userData.isVendor = user['isVendor'];
        userData.department_id = user['department_id'];
        userData.user_role = user['user_role'];
        userData.facebook_url = user['facebook_url']
        userData.youtube_url = user['youtube_url']
        userData.google_url = user['google_url']
        userData.linkedIn_url = user['linkedIn_url']
        userData.twitter_url = user['twitter_url']
        userData.job_title = user['job_title']
        userData.alert_status = user['alert_status']
        userData.pcb_permissions = pcb_permissions
        userData.logged_in = true;
        userData.login_time = moment().format('h:mm:ss A');
        userData.added_by_client =user['added_by_client']
        userData.parent_id =user['parent_id']
        userData.parent_user_type =user['parent_user_type']
        userData.isFromClient =isFromClient
        userData.isFromAdmin =isFromAdmin
        userData.parent_client_name =user['parent_client_name']
        userData.hourly_rate =user['hourly_rate']
        userData.isClient =user['isClient']

        userData.timeOut = 999999;
        console.log("user['user_permissions']", user.user_permissions);
        userData.user_permissions = user['user_permissions'] && user['user_permissions'].split(',');
        console.log("userData.user_permissions", userData.user_permissions);

        userData.last_activity = Math.round(moment().valueOf() / 1000);

        userData.token = token;
        userData.loggedAt = Math.round(moment().valueOf() / 1000);


        const privilegeResult = await Login.isPrivileged(userData.user_permissions);
        console.log("privilegeResult - ", privilegeResult);
        if (privilegeResult) {
          explodedPermissions = privilegeResult.map(entry => entry.privileges);
          console.log("explodedPermissions - ", explodedPermissions);
        }

        userData['exploded_permissions'] = explodedPermissions;

        // If user has "Administrator Access" permission, treat as admin and grant full role-1 permissions
        if (explodedPermissions && explodedPermissions.includes('Administrator Access')) {
          userData.user_type = 1;
          const adminPermissionsStr = await Login.getPermissionsForRoleId(1);
          userData['adminPermissionsStr'] = adminPermissionsStr;
          if (adminPermissionsStr) {
            const adminPermIds = adminPermissionsStr.split(',').map((id) => id.trim()).filter(Boolean);
            userData.user_permissions = adminPermIds;
            const adminPrivilegeResult = await Login.isPrivileged(adminPermIds.join(','));
            if (adminPrivilegeResult && adminPrivilegeResult.length > 0) {
              explodedPermissions = adminPrivilegeResult.map((entry) => entry.privileges);
              userData['exploded_permissions'] = explodedPermissions;
            }
          }
        }

        if (user.user_type != 3 && explodedPermissions.includes('Calls') && !user.worker_sid) {
          const workerSid = await createTwilioSupportWorker(user.user_id, `${user.first_name}_${user.last_name}`, user.department_id);
          if (workerSid) {
            userData.worker_sid = workerSid;
            await Admin.updateUser(user.user_id, { worker_sid: workerSid });
          }
        }

        if (user['user_type'] != 3 && explodedPermissions.includes('Calls') && !empty(user['worker_sid'])) {
          userData['worker_sid'] = user['worker_sid'];
        }
        let thisMonth = moment().format('MMMM');

        let theDate = moment().format('YYYY-MM-DD');
        let currentMonth = moment().format('MM');
        let weekNo = moment(theDate).add(1, 'days').week();
        let weekNum = (currentMonth === '12' && weekNo === 1) ? '52' : weekNo;

        // Get the current date/time
        let curDateTime = moment().format('YYYY-MM-DD HH:mm:ss');

      
        let data = {
          userId:user['user_id'],
          // name: user.first_name + ' ' + user.last_name,
          weekNo: weekNum,
          clockYear: moment().format('YYYY'),
          entryDate: curDateTime,
          startTime: curDateTime,
          entryType: 1,
          lastUpdated: curDateTime
        };
        console.log("###########################",data);
        let insertLog=await Login.addLog(data);
        console.log("###########################",insertLog);
        reply.send({ status: 1, user: userData, accessToken: token, message: 'Login successful' });

      } else {
        reply.code(401).send({ error: 'Invalid password' });
      }
    } else {
      reply.code(401).send({ error: 'User not found or not active' });
    }

  } catch (err) {
    console.error(err);
    reply.code(500).send({ error: 'Server error' });
  }
};

const loginWithPin = async (req, reply) => {
  const { pin, isFromClient, isFromAdmin, currentUserId } = req.body;

  try {
    console.log("loginWithPin - PIN received:", pin);
    const results = await Login.userLoginByPin(pin);
    console.log("loginWithPin - Query results:", results ? "User found" : "No user found");

    if (results && !results.error) {
      const user = results;

      // Prevent switching to the same account using its own PIN (for ANY user type)
      if (currentUserId && Number(currentUserId) === Number(user.user_id)) {
        console.log("loginWithPin - Attempt to switch with own PIN blocked");
        return reply.code(400).send({
          status: 0,
          error: 'You cannot switch to your own account using PIN.',
        });
      }

      let active = {};
      let explodedPermissions = {};
      let userData = {};
      active['active'] = 'Y';
      await Admin.updateUser(user.user_id, active);
      const token = jwt.sign({ userId: user.user_id }, JWT_SECRET, { expiresIn: 24 * 60 * 60 });
      let companyDetail = await Settings.getCompanyProfileDetails()
      let pcb_permissions = await Settings.getPCBPermission()

      userData.user_id = user['user_id'];
      userData.team_id = user['team_id'];
      userData.client_id = user['client_id'] || user['partner_client_id'];
      userData.driver_id = user['driver_id'];
      userData.driverId = user['driver_id'];
      userData.company_name = companyDetail[0].name;
      userData.first_name = user['name'] || user['first_name'];
      userData.username = user['username'];
      userData.last_name = user['last_name'];
      userData.person_name = `${user['first_name']} ${user['last_name']}`;
      userData.email = user['email'];
      userData.profile_pic = user['profile_pic'] != '' ? user['profile_pic'] : 'avatar.jpg';
      userData.company_logo = (user['company_logo'] != '' || !user.company_logo) ? companyDetail[0].company_logo : 'default_logo.jpg';
      userData.user_type = user['user_type'];
      userData.isVendor = user['isVendor'];
      userData.department_id = user['department_id'];
      userData.user_role = user['user_role'];
      userData.facebook_url = user['facebook_url']
      userData.youtube_url = user['youtube_url']
      userData.google_url = user['google_url']
      userData.linkedIn_url = user['linkedIn_url']
      userData.twitter_url = user['twitter_url']
      userData.job_title = user['job_title']
      userData.alert_status = user['alert_status']
      userData.pcb_permissions = pcb_permissions
      userData.logged_in = true;
      userData.login_time = moment().format('h:mm:ss A');
      userData.added_by_client = user['added_by_client']
      userData.parent_id = user['parent_id']
      userData.parent_user_type = user['parent_user_type']
      userData.isFromClient = isFromClient
      userData.isFromAdmin = isFromAdmin
      userData.parent_client_name = user['parent_client_name']
      userData.hourly_rate = user['hourly_rate']
      userData.isClient = user['isClient']

      userData.timeOut = 999999;
      userData.user_permissions = user['user_permissions'] && user['user_permissions'].split(',');
      userData.last_activity = Math.round(moment().valueOf() / 1000);
      userData.token = token;
      userData.loggedAt = Math.round(moment().valueOf() / 1000);

      const privilegeResult = await Login.isPrivileged(userData.user_permissions);
      if (privilegeResult) {
        explodedPermissions = privilegeResult.map(entry => entry.privileges);
      }

      userData['exploded_permissions'] = explodedPermissions;

      if (user.user_type != 3 && explodedPermissions.includes('Calls') && !user.worker_sid) {
        const workerSid = await createTwilioSupportWorker(user.user_id, `${user.first_name}_${user.last_name}`, user.department_id);
        if (workerSid) {
          userData.worker_sid = workerSid;
          await Admin.updateUser(user.user_id, { worker_sid: workerSid });
        }
      }

      if (user['user_type'] != 3 && explodedPermissions.includes('Calls') && !empty(user['worker_sid'])) {
        userData['worker_sid'] = user['worker_sid'];
      }
      
      let thisMonth = moment().format('MMMM');
      let theDate = moment().format('YYYY-MM-DD');
      let currentMonth = moment().format('MM');
      let weekNo = moment(theDate).add(1, 'days').week();
      let weekNum = (currentMonth === '12' && weekNo === 1) ? '52' : weekNo;
      let curDateTime = moment().format('YYYY-MM-DD HH:mm:ss');

      let data = {
        userId: user['user_id'],
        weekNo: weekNum,
        clockYear: moment().format('YYYY'),
        entryDate: curDateTime,
        startTime: curDateTime,
        entryType: 1,
        lastUpdated: curDateTime
      };
      
      let insertLog = await Login.addLog(data);
      reply.send({ status: 1, user: userData, accessToken: token, message: 'Login successful' });
    } else {
      console.log("loginWithPin - No user found or invalid PIN");
      reply.code(401).send({ status: 0, error: 'Invalid PIN or user not found. Please check the PIN and try again.' });
    }
  } catch (err) {
    console.error("loginWithPin - Error:", err);
    reply.code(500).send({ status: 0, error: 'Server error' });
  }
};

const updateSimpleViewStatus = async (request, reply) => {
  try {
    const { userId, simpleViewEnabled } = request.body;
    const success = await Admin.updateSimpleViewStatusByUserId(userId, simpleViewEnabled ? 1 : 0);
    if (success) {
      reply.send({ status: 1, message: 'Simple view status updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update simple view status.' });
    }
  } catch (error) {
    console.error('Error in updateSimpleViewStatus controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getSimpleViewStatus = async (request, reply) => {
  try {
    const { userId } = request.body;
    const status = await Admin.getSimpleViewStatusByUserId(userId);
    reply.send({ status: 1, data: { simpleViewEnabled: status } });
  } catch (error) {
    console.error('Error in getSimpleViewStatus controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateClientViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateClientViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Client view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update client view type.' });
    }
  } catch (error) {
    console.error('Error in updateClientViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getClientViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getClientViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getClientViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateVendorViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateVendorViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Vendor view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update vendor view type.' });
    }
  } catch (error) {
    console.error('Error in updateVendorViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getVendorViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getVendorViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getVendorViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateCommunityViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateCommunityViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Community view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update community view type.' });
    }
  } catch (error) {
    console.error('Error in updateCommunityViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getCommunityViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getCommunityViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getCommunityViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateAdminViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateAdminViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Admin view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update admin view type.' });
    }
  } catch (error) {
    console.error('Error in updateAdminViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getAdminViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getAdminViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getAdminViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateProjectViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateProjectViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Project view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update project view type.' });
    }
  } catch (error) {
    console.error('Error in updateProjectViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getProjectViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getProjectViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getProjectViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateCommunityDesignViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateCommunityDesignViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Community design view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update community design view type.' });
    }
  } catch (error) {
    console.error('Error in updateCommunityDesignViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getCommunityDesignViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getCommunityDesignViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getCommunityDesignViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateCommunityInstallViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateCommunityInstallViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Community install view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update community install view type.' });
    }
  } catch (error) {
    console.error('Error in updateCommunityInstallViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getCommunityInstallViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getCommunityInstallViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getCommunityInstallViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateCommunityJobViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateCommunityJobViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Community job view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update community job view type.' });
    }
  } catch (error) {
    console.error('Error in updateCommunityJobViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getCommunityJobViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getCommunityJobViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getCommunityJobViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateCommunityOfficialRequestViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateCommunityOfficialRequestViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Community official request view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update community official request view type.' });
    }
  } catch (error) {
    console.error('Error in updateCommunityOfficialRequestViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getCommunityOfficialRequestViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getCommunityOfficialRequestViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getCommunityOfficialRequestViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateDesignOrderViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateDesignOrderViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Design order view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update design order view type.' });
    }
  } catch (error) {
    console.error('Error in updateDesignOrderViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getDesignOrderViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getDesignOrderViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getDesignOrderViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateDesignOrderJobViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateDesignOrderJobViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Design order job view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update design order job view type.' });
    }
  } catch (error) {
    console.error('Error in updateDesignOrderJobViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getDesignOrderJobViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getDesignOrderJobViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getDesignOrderJobViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateInstallationViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateInstallationViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Installation view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update installation view type.' });
    }
  } catch (error) {
    console.error('Error in updateInstallationViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getInstallationViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getInstallationViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getInstallationViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateOfficialRequestViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateOfficialRequestViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Official request view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update official request view type.' });
    }
  } catch (error) {
    console.error('Error in updateOfficialRequestViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getOfficialRequestViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getOfficialRequestViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getOfficialRequestViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updatePickupViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updatePickupViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Pickup view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update pickup view type.' });
    }
  } catch (error) {
    console.error('Error in updatePickupViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getPickupViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getPickupViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getPickupViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateProposalViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateProposalViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Proposal view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update proposal view type.' });
    }
  } catch (error) {
    console.error('Error in updateProposalViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getProposalViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getProposalViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getProposalViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateQuotationViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateQuotationViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Quotation view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update quotation view type.' });
    }
  } catch (error) {
    console.error('Error in updateQuotationViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getQuotationViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getQuotationViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getQuotationViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateShippingViewType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateShippingViewTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'Shipping view type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update shipping view type.' });
    }
  } catch (error) {
    console.error('Error in updateShippingViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getShippingViewType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getShippingViewTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getShippingViewType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateViewProjectType = async (request, reply) => {
  try {
    const { userId, viewType } = request.body;
    const success = await Admin.updateViewProjectTypeByUserId(userId, viewType);
    if (success) {
      reply.send({ status: 1, message: 'View project type updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update view project type.' });
    }
  } catch (error) {
    console.error('Error in updateViewProjectType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getViewProjectType = async (request, reply) => {
  try {
    const { userId } = request.body;
    const viewType = await Admin.getViewProjectTypeByUserId(userId);
    reply.send({ status: 1, data: { viewType } });
  } catch (error) {
    console.error('Error in getViewProjectType controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateProjectFilters = async (request, reply) => {
  try {
    const {
      userId,
      teamFilter = [],
      clientFilter = [],
      communityFilter = [],
      userFilter = [],
      jobClassFilter = [],
      jobTypeFilter = [],
      salesRepFilter = [],
      projectTypeFilter = 'ALL',
      dueFilter = 1,
      sortFilter = 'new',
      fromDate = null,
      toDate = null,
      pageKey = 'production',
      appointmentFilter = null,  // { id, name, project_id } or null
    } = request.body;

    const success = await ProjectFilterPreference.updateProjectFiltersByUserId(
      userId,
      {
        teamFilter,
        clientFilter,
        communityFilter,
        userFilter,
        jobClassFilter,
        jobTypeFilter,
        salesRepFilter,
        projectTypeFilter,
        dueFilter,
        sortFilter,
        fromDate,
        toDate,
        appointmentFilterId: appointmentFilter?.project_id || appointmentFilter?.id || null,
        appointmentFilterName: appointmentFilter?.name || null,
      },
      pageKey
    );

    if (success) {
      reply.send({ status: 1, message: 'Project filters updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update project filters.' });
    }
  } catch (error) {
    console.error('Error in updateProjectFilters controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getProjectFilters = async (request, reply) => {
  try {
    const { userId, pageKey = 'production' } = request.body;
    const data = await ProjectFilterPreference.getProjectFiltersByUserId(
      userId,
      pageKey
    );
    reply.send({ status: 1, data });
  } catch (error) {
    console.error('Error in getProjectFilters controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const deleteProjectFilters = async (request, reply) => {
  try {
    const { userId, pageKey = 'production' } = request.body;
    const success = await ProjectFilterPreference.deleteProjectFiltersByUserId(
      userId,
      pageKey
    );

    if (success) {
      reply.send({ status: 1, message: 'Project filters deleted successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'No project filters found to delete.' });
    }
  } catch (error) {
    console.error('Error in deleteProjectFilters controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const getUserPin = async (request, reply) => {
  try {
    const { userId } = request.body;
    const pin = await Admin.getUserPinByUserId(userId);
    if (pin !== null) {
      reply.send({ status: 1, pin, message: 'PIN fetched successfully.' });
    } else {
      reply.code(404).send({ status: 0, message: 'PIN not found.' });
    }
  } catch (error) {
    console.error('Error in getUserPin controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

const updateUserPin = async (request, reply) => {
  try {
    const { userId } = request.body;
    const newPin = await generateUniquePin(sequelize);
    const success = await Admin.updateUserPinByUserId(userId, newPin);
    if (success) {
      reply.send({ status: 1, pin: newPin, message: 'PIN updated successfully.' });
    } else {
      reply.code(400).send({ status: 0, message: 'Failed to update PIN.' });
    }
  } catch (error) {
    console.error('Error in updateUserPin controller:', error);
    reply.code(500).send({ status: 0, message: 'Internal server error.' });
  }
};

// BACKUP: Original notifications function without pagination
// const notifications = async (req, reply) => {
//   let userId = req.body.userId
//   let notifications = await Admin.getAllNotifications(userId)
//   let notificationCount = await Admin.getAllNotificationsCount(userId)
//   reply.send({
//     status: 1, notifications, notificationCount,
//     msg: "Notifications fetch success fully"
//   })
// }

// NEW: notifications function with pagination support
const notifications = async (req, reply) => {
  let userId = req.body.userId
  let page = req.body.page || 1  // Default to page 1 if not provided
  let limit = 6  // Fixed limit of 6 items per page
  
  let notifications = await Admin.getAllNotifications(userId, page, limit)
  let notificationCount = await Admin.getAllNotificationsCount(userId)
  let totalNotificationsCount = await Admin.getTotalNotificationsCount(userId)
  
  reply.send({
    status: 1, 
    notifications, 
    notificationCount,
    totalCount: totalNotificationsCount, // Total count for pagination
    pagination: {
      currentPage: page,
      limit: limit,
      hasMore: notifications.length === limit  // If we got exactly 'limit' items, there might be more
    },
    msg: "Notifications fetch success fully"
  })
}
const updateNotifications=async(req,reply)=>{
  let userId=req.body.userId
  let data={}
  // data['noti_count']=await Admin.fetchNotificationCount(userId);
  let notification={}
  notification['noti_count']=0;
  let update=await Admin.updateUser(userId,notification)
  let updateNotification=await Admin.updateNotification( {status:0},userId)
console.log("##############",updateNotification);
  let notifications = await Admin.getAllNotifications(userId)
  let notificationCount = await Admin.getAllNotificationsCount(userId)
  reply.send({
    status: 1, notifications, notificationCount,
    msg: "Notifications fetch success fully"
  })
  
}
const userSignup = async (req, reply) => {
  let values = req.body.values


  let user = {}
  user['first_name'] = values.name
  user['last_name'] = values.lastName
  user['company_name'] = values.name
  user['email'] = values.email
  user['terms_and_policy'] = values.terms_and_policy
  user['username'] = user['email'];
  let hashedPassword = Password.hash(values.password);
  user['password'] = hashedPassword;
  user['profile_pic'] = 'avatar.jpg';
  user['status'] = 1;
  user['user_type'] = 3;
  // Generate unique PIN for user
  user['user_pin_unique'] = await generateUniquePin(sequelize);
  console.log("$$$$$$$$$$$", await Admin.getUserByEmail(user['email']));
  if (empty(await Admin.getUserByEmail(user['email']))) {
    let userId = await Admin.addUser(user);
    if (userId) {
      let partner = {}
      partner['name'] = user['company_name'];
      partner['last_name'] = user['last_name']
      partner['email'] = user['email'];
      partner['phone'] = values.phone
      partner['city'] = values.city
      partner['state_id'] = values.state.id
      let access_link = req.body.link
      if (!empty(access_link)) {
        partner['partner_type'] = access_link['partner_type_id'];
        partner['workflows'] = access_link['workflow_ids'];
        if (!empty(access_link['partner_id'])) {
          let partner_id = access_link['partner_id'];
          let partner_data = await Client.getClientById(partner_id)
          console.log("%%%%%%%%", partner_data);
          if (partner_data['workflows'] && partner_data['workflows'].trim() !== '') {

            partner_data['workflows'] = partner_data['workflows'].split(',');
          } else {
            partner_data['workflows'] = [];
          }
          let workflow_ids = partner['workflows'].split(',');
          console.log("###Nussssh", workflow_ids);
          console.log("###Nussssh", partner_data['workflows']);
          workflow_ids = Array.from(new Set([...workflow_ids, ...partner_data['workflows']]));
          console.log("###Nush", workflow_ids);
          partner['workflows'] = workflow_ids.join(',');
          partner['user_id'] = userId;
          partner['status'] = 1;
          let updated = await Client.updateClient(partner, partner_id);
        }
        else if (!empty(await Client.getPartnerByEmailData(partner['email']))) {
          let partner_data = Client.getPartnerByEmailData(partner['email']);
          let partner_id = partner_data['id'];
          if (!empty(partner_data['workflows'])) {
            partner_data['workflows'] = partner_data['workflows'].split(",");
          } else {
            partner_data['workflows'] = array();
          }
          let workflow_ids = partner['workflows'].split(',');
          workflow_ids = Array.from(new Set([...workflow_ids, ...partner_data['workflows']]));
          partner['workflows'] = workflow_ids.split(',')
          partner['user_id'] = userId
          partner['status'] = 1;
          let updated = await Client.updateClient(partner, partner_id);
        } else {
          partner['timestamp'] = moment().unix();
          partner['user_id'] = userId;
          partner['status'] = 1;
          let partner_id = await Client.addClient(partner);
        }
        let subject = portalName + " - Your account has been activated";
        let welcome = "Hello " + user['company_name'] + ","
        let email_content = `Thank you for creating your account. Your username (email address) and password is included for reference below.`;
        sgMail.setApiKey(SENDGRID_API_KEY)
        let message = activateProfile()
        console.log("$$$$$$$$$$$$", user['username']);
        message = message.replace('[emailContent]', email_content)
        message = message.replace('[CONTENT]', welcome)
        message = message.replace('[NAME]', user['username'])
        message = message.replace('[PASSWORD]', values.password)
        message = message.replace('[LOGIN_URL]', `${BASE_URL}`)
        // const msg = {
        //   to: user.email, // Change to your recipient
        //   from: 'nushara@skyniche.com', // Change to your verified sender
        //   subject: subject,
        //   text: subject,
        //   html: message,
        // }
        // sgMail
        //   .send(msg)
        //   .then(() => {
        //     console.log('Email sent')
        //   })
        //   .catch((error) => {
        //     console.error(error)
        //   })

        const mailOptions = {
          to:  user.email,  
          from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
          subject: subject,
          text: subject,
          html: message,
        }
        try {
        if(SEND_EMAIL){

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

        let adminEmails = await Admin.getAllAdminEmails();
        let adminSubject = portalName + " - A new user has been registered";
        let adminWelcome = "Hello ! Admin" + ","
        let admin_email_content = `A new user has been registered`;
        let adminMessage = activateProfile()
        adminMessage = adminMessage.replace('[emailContent]', admin_email_content)
        adminMessage = adminMessage.replace('[CONTENT]', adminWelcome)
        adminMessage = adminMessage.replace('[NAME]', user['username'])
        adminMessage = adminMessage.replace('[PASSWORD]', values.password)
        adminMessage = adminMessage.replace('[LOGIN_URL]', `${BASE_URL}`)
        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: adminSubject,
          //   text: adminSubject,
          //   html: adminMessage,
          // }
          // 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: adminSubject,
            text: adminSubject,
            html: adminSubject,
          }
          try {
        if(SEND_EMAIL){

            await transporter.sendMail(mailOptions);
            console.log('Email sent');
        }
          } catch (error) {
            console.error('##########Err', error);
           
          }
        }
        reply.send({ status: 1, message: "Your account has been created!." })

      }
      reply.send({ status: 1, message: "Your account has been created!." })
    }
  }
  reply.send({ status: 0, message: "Email id already exists, Failed to  create Account!." })
}

const activateLink = async (req, reply) => {
  try {
    let token = req.body.token
    let link = await Client.getInviteLinkToken(token)
    let state = await Client.getAllStates()
    if (!empty(link)) {
      let partner_id = link[0]['partner_id'];
      let partner_data = await Client.getClientById(partner_id)
      reply.send({ status: 1, link, state, partner_data })
    }

    reply.send({ status: 1, link: [], state })
  }
  catch (error) {
    reply.status(500).send({ message: "Server error" + error })
  }
}

const logOut=async(req,reply)=>{
  console.log("Enter to logout");
  let {userId}=req.body
  let  data={}
  data['active']="N"
  data['last_activity']=moment().unix();
  let update=await Admin.updateUser(userId,data)
  if(update){
    let curDateTime = moment().format('YYYY-MM-DD HH:mm:ss');
    let theDate = moment().format('YYYY-MM-DD');
    let currentMonth = moment().format('MM');
    let weekNo = moment().week();
    let weekNum = currentMonth === '12' && weekNo === 1 ? '52' : weekNo;
    let logId=await Login.getLogId(userId,weekNum,moment().format('YYYY'))
    console.log("################",logId);
    let log = {
      endTime: curDateTime,
      lastUpdated: curDateTime,
    };
  let updateLog=await Login.updateLog(log,logId.timeId)
    reply.send({status:1,message:"Logout Successfully"})
  }
}

const activeTeam=async(req, reply)=>{
  let activeTeam=await Login.getAllActiveTeams()
  reply.send({status:1, activeTeam})
}

const logoutAll=async(req, reply)=>{
  let activeTeam=await Login.getAllActiveTeams()
  console.log("hifiiiiiiiiiiiiiiiiiii");
  for(const row of activeTeam){
    let data={}
    data['active']="N"
    data['last_activity']=moment().unix();
    let update=await Admin.updateUser(row['id'],data)
    // const result = await ProjectTask.fetchClockedInStaffTaskTimelog(row['id'])
    console.log("hifiiiiiiiiiiiiiiiiiii",update);
  let curDateTime = moment().format('YYYY-MM-DD HH:mm:ss');
    let theDate = moment().format('YYYY-MM-DD');
    let currentMonth = moment().format('MM');
    let weekNo = moment().week();
    let weekNum = currentMonth === '12' && weekNo === 1 ? '52' : weekNo;
    let logId=await Login.getLogId(row['id'],weekNum,moment().format('YYYY'))
    console.log("################",logId);

    // Only update the log if the user has an active (incomplete) timelog
    if (logId && logId.timeId) {
      let log = {
        endTime: curDateTime,
        lastUpdated: curDateTime,
      };
      let updateLog=await Login.updateLog(log,logId.timeId)
      console.log("Updated log for user", row['id'], ":", updateLog);
    } else {
      console.log("No active timelog found for user", row['id'], "- skipping log update");
      return reply.send({status:2, message:"No active timelog found for user",})
    }
  }
  reply.send({status:1, message:"Logout successfully",})
}

const checkActiveUser=async(req, reply)=>{
  let userId=req.body.userId
  let checkActiveUser=await Login.checkActiveUser(userId)
  if(checkActiveUser){
    reply.send({status:1, message:"Active User",active:true})
  }
  else{
    reply.send({status:0, message:"Inactive User", active:false})
  }
  
}

const staffTime=async(req, reply)=>{
  let WhereCondition=""
  let filter=req.body.filter
  const today = new Date();
  if(filter==1){
 
  const todayString = today.toISOString().split('T')[0];
   WhereCondition=`AND DATE(entryDate) = '${todayString}'`
  }
  else if(filter==2){
    console.log("#############################Enterrr 2");
    const firstDayOfWeek = new Date(today.setDate(today.getDate() - today.getDay()));
    const lastDayOfWeek = new Date(today.setDate(today.getDate() - today.getDay() + 6));
    const firstDayOfWeekString = firstDayOfWeek.toISOString().split('T')[0];
    const lastDayOfWeekString = lastDayOfWeek.toISOString().split('T')[0];
     WhereCondition=` AND DATE(entryDate) BETWEEN '${firstDayOfWeekString}' AND '${lastDayOfWeekString}'`
  }
  else if(filter==3){
 
    const month = today.getMonth() + 1; 
    console.log("#############################Enterrr 3",month);
    const firstDayOfMonth = new Date(today.getFullYear(), month - 1, 1);
    const lastDayOfMonth = new Date(today.getFullYear(), month, 0);
    const firstDayOfMonthString = firstDayOfMonth.toISOString().split('T')[0];
    const lastDayOfMonthString = lastDayOfMonth.toISOString().split('T')[0];
    console.log("#############################Enterrr 3",lastDayOfMonth);
    WhereCondition=` AND DATE(entryDate) BETWEEN '${firstDayOfMonthString}' AND '${lastDayOfMonthString}'`
  }
  else{
    WhereCondition=""
  }
  let staffTime=await Login.getAllStaffTime(WhereCondition)
  reply.send({status:1, staffTime})
}

const resetPasswordFromProfile = async(request,reply) =>{
  try{
    const { userId, oldPassword, newPassword } = request.body;
    const currentDate = Math.round(moment().valueOf() / 1000);
    const userResult = await Login.checkOldPassword(userId)
    if (await Password.verify(oldPassword, userResult.password)) {
      const isTeamMember = await Admin.isTeamMemberByUserId(userId);
      console.log("isTeamMember",isTeamMember);
      if(isTeamMember){
        const existingTeamByPhone = await Teams.getTeamByPhoneNumAndPassword(isTeamMember[0].phone,newPassword,isTeamMember[0].id);
        console.log("existingTeamByPhone",existingTeamByPhone);
        if(existingTeamByPhone){
          return reply.send({status:4, message:"This password cannot be used, Please choose a different one."})
        }
      }
      let data = {}
      const hashedNewPassword = Password.hash(newPassword);
      data['password'] = hashedNewPassword;
      data['admin_password'] = newPassword;
      const updatedData = await Admin.updateUser(userId,data)
      if(updatedData){
      // Notification
      let notificationMsg = `Your password has been updated successfully`;
      let notificationUrl = "login";

      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 = {};
      notificationMsg = `Password updated successfully for "${userResult.first_name} ${userResult.last_name}"`;
      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:"Password updated successfully"})
      }
      else{
        reply.send({status:2,message:"Error updating password"})
      }
    }
    else{
      console.log("Wrong password")
      reply.send({status:3, message:"Wrong password"})
    }
  }
  catch(error){
    reply.send({status:500, message:"Server error"})
    console.log("Error resetPasswordFromProfile",error)
  }
}

const getAdminData = async(req,res) => {
  try{
    const {userId} = req.body;
    const result = await Login.getAdminData(userId)
    if(result){
      res.send({status:1,message:"Data fetched successfully",adminData:result})
    }
  }
  catch(error){
    console.log("getAdminData error - ",error);
    res.send({status:500,message:"Error fetching data",errorData:error})
  }
}

const updateAdminProfile = async(req,res) => {
  try{
    const {values,userId} = req.body;
    let data = {};
    console.log("values.first_name----------",values.firstname);

    let getTeamByEmailData = false;
    if (values?.email?.trim()) {
      getTeamByEmailData = await Teams.getTeamByEmail(values.email);
    }

    data['first_name'] = values.firstname;
    data['last_name'] = values.lastName;
    data['email'] = values.email;
    if(!getTeamByEmailData){
      data['username'] = values.email;
    }
    data['personal_timezone'] = values.personalTimezone;
    data['date_format'] = values.dateFormat;
    data['time_format'] = values.timeFormat;
    const result = await Admin.updateUser(userId,data)

    const teamData = await Teams.getTeamByUserId(userId);
    if(teamData && teamData?.id){
      let team = {
        first_name : values.firstname,
        last_name : values.lastName,
        email : values.email
      }
      const updateTeamResult = await Teams.updateTeam(teamData?.id, team);
    }

    if(result){
      res.send({status:1,message:"Profile data updated successfully"})
    }
    else{
      res.send({status:0,message:"Error updating profile"})
    }
  }
  catch(error){
    console.log("Error updating profile - ",error);
    res.send({status:500,message:"Server Error", error:"Error updating profile - "+error})
  }
}

const getSidebarPermissions = async (req, res) => {
  try {
    const {userId} = req.body;
    const results = await Login.getSidebarPermissions(userId)
    if(results){
      res.send({status:1,permissionData:results.formattedData,orderData:results.sidebarOrder });
    }else{
      res.send({status:0,permissionData:[]});
    }
  } catch (error) {
    console.error('Error fetching sidebar permissions:', error);
    res.send({status:500,permissionData:[], error:error});
  }
};

const updateSidebarOrder = async (req, res) => {
  try {
    const {userId,newOrder} = req.body;
    const results = await Login.updateUserSidebarOrder(userId, newOrder)
    if(results){
      res.send({status:1,permissionData:results.formattedData,orderData:results.sidebarOrder });
    }else{
      res.send({status:0,permissionData:[]});
    }
  } catch (error) {
    console.error('Error fetching sidebar permissions:', error);
    res.send({status:500,permissionData:[], error:error});
  }
};

const getChatPostitionByUser = async (req, res) => {
  try {
    const {userId} = req.body;
    const results = await Admin.chatPositionByUser(userId)
    if(results){
      res.send({status:1,position_x:results.chat_position_x,position_y:results.chat_position_y });
    }else{
      res.send({status:0,data:[]});
    }
  } catch (error) {
    console.error('Error fetching sidebar permissions:', error);
    res.send({status:500,data:[], error:error});
  }
};

const updateChatPostitionByUser = async (req, res) => {
  try {
    const {userId ,chat_position_x,chat_position_y } = req.body;
    const results = await Admin.updateChatPositionByUserId(userId,chat_position_x,chat_position_y)
    if(results){
      res.send({status:1,message:"Chat position updated successful" });
    }else{
      res.send({status:0,data:[]});
    }
  } catch (error) {
    console.error('Error fetching sidebar permissions:', error);
    res.send({status:500,data:[], error:error});
  }
};


const userSignupUpdate = async (req, reply) => {
  let values = req.body.values
 let userId = values.userId 

  let user = {}
  user['first_name'] = values.name
  user['last_name'] = values.lastName
  user['company_name'] = values.name
  user['email'] = values.email
  user['terms_and_policy'] = values.terms_and_policy
  user['username'] = user['email'];
  let hashedPassword = Password.hash(values.password);
  user['password'] = hashedPassword;
  user['profile_pic'] = 'avatar.jpg';
  user['status'] = 1;
  user['user_type'] = 3;
  console.log("$$$$$$$$$$$", await Admin.getUserByEmail(user['email']));
  if (empty(await Admin.getUserByEmail(user['email'])) || userId) {
    let updateUser = false
    if(!userId) {
       updateUser = await Admin.addUser(user);
    }else{
      updateUser = await Admin.updateUser(userId,user);
    }
    if (updateUser) {
      let partner = {}
      partner['name'] = user['company_name'];
      partner['last_name'] = user['last_name']
      partner['email'] = user['email'];
      partner['phone'] = values.phone
      partner['city'] = values.city
      partner['state_id'] = values.state.id
      let access_link = req.body.link
      if (!empty(access_link)) {
        partner['partner_type'] = access_link['partner_type_id'];
        partner['workflows'] = access_link['workflow_ids'];
        if (!empty(access_link['partner_id'])) {
          let partner_id = access_link['partner_id'];
          let partner_data = await Client.getClientById(partner_id)
          console.log("%%%%%%%%", partner_data);
          if (partner_data['workflows'] && partner_data['workflows'].trim() !== '') {

            partner_data['workflows'] = partner_data['workflows'].split(',');
          } else {
            partner_data['workflows'] = [];
          }
          let workflow_ids = partner['workflows'].split(',');
          console.log("###Nussssh", workflow_ids);
          console.log("###Nussssh", partner_data['workflows']);
          workflow_ids = Array.from(new Set([...workflow_ids, ...partner_data['workflows']]));
          console.log("###Nush", workflow_ids);
          partner['workflows'] = workflow_ids.join(',');
          partner['user_id'] = userId;
          partner['status'] = 1;
          let updated = await Client.updateClient(partner, partner_id);
        }
        else if (!empty(await Client.getPartnerByEmailData(partner['email']))) {
          let partner_data = Client.getPartnerByEmailData(partner['email']);
          let partner_id = partner_data['id'];
          if (!empty(partner_data['workflows'])) {
            partner_data['workflows'] = partner_data['workflows'].split(",");
          } else {
            partner_data['workflows'] = array();
          }
          let workflow_ids = partner['workflows'].split(',');
          workflow_ids = Array.from(new Set([...workflow_ids, ...partner_data['workflows']]));
          partner['workflows'] = workflow_ids.split(',')
          partner['user_id'] = userId
          partner['status'] = 1;
          let updated = await Client.updateClient(partner, partner_id);
        } else {
          partner['timestamp'] = moment().unix();
          partner['user_id'] = userId;
          partner['status'] = 1;
          let partner_id = await Client.addClient(partner);
        }
        let subject = portalName + " - Your account has been activated";
        let welcome = "Hello " + user['company_name'] + ","
        let email_content = `Thank you for creating your account. Your username (email address) and password is included for reference below.`;
        sgMail.setApiKey(SENDGRID_API_KEY)
        let message = activateProfile()
        console.log("$$$$$$$$$$$$", user['username']);
        message = message.replace('[emailContent]', email_content)
        message = message.replace('[CONTENT]', welcome)
        message = message.replace('[NAME]', user['username'])
        message = message.replace('[PASSWORD]', values.password)
        message = message.replace('[LOGIN_URL]', `${BASE_URL}`)
        // const msg = {
        //   to: user.email, // Change to your recipient
        //   from: 'nushara@skyniche.com', // Change to your verified sender
        //   subject: subject,
        //   text: subject,
        //   html: message,
        // }
        // sgMail
        //   .send(msg)
        //   .then(() => {
        //     console.log('Email sent')
        //   })
        //   .catch((error) => {
        //     console.error(error)
        //   })

        const mailOptions = {
          to:  user.email,  
          from: '"SignWise Solutions" <noreply@signwisesolutions.com>', //'nushara@skyniche.com', // Change to your verified sender
          subject: subject,
          text: subject,
          html: message,
        }
        try {
        if(SEND_EMAIL){

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

        let adminEmails = await Admin.getAllAdminEmails();
        let adminSubject = portalName + " - A new user has been registered";
        let adminWelcome = "Hello ! Admin" + ","
        let admin_email_content = `A new user has been registered`;
        let adminMessage = activateProfile()
        adminMessage = adminMessage.replace('[emailContent]', admin_email_content)
        adminMessage = adminMessage.replace('[CONTENT]', adminWelcome)
        adminMessage = adminMessage.replace('[NAME]', user['username'])
        adminMessage = adminMessage.replace('[PASSWORD]', values.password)
        adminMessage = adminMessage.replace('[LOGIN_URL]', `${BASE_URL}`)
        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: adminSubject,
          //   text: adminSubject,
          //   html: adminMessage,
          // }
          // 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: adminSubject,
            text: adminSubject,
            html: adminSubject,
          }
          try {
        if(SEND_EMAIL){

            await transporter.sendMail(mailOptions);
            console.log('Email sent');
        }
          } catch (error) {
            console.error('##########Err', error);
           
          }
        }
        reply.send({ status: 1, message: "Your account has been created!." })

      }
      reply.send({ status: 1, message: "Your account has been created!." })
    }
  }
  reply.send({ status: 0, message: "Email id already exists, Failed to  create Account!." })
}



module.exports = {
  login,
  updateSimpleViewStatus,
  getSimpleViewStatus,
  notifications,
  userSignup,
  activateLink,
  logOut,
  activeTeam,
  logoutAll,
  checkActiveUser,
  staffTime,
  resetPasswordFromProfile,
  getAdminData,
  updateAdminProfile,
  updateNotifications,
  loginWithUserId,
  loginWithPin,
  getSidebarPermissions,
  updateSidebarOrder,
  getChatPostitionByUser,
  updateChatPostitionByUser,
  userSignupUpdate,
  updateClientViewType,
  getClientViewType,
  updateVendorViewType,
  getVendorViewType,
  updateCommunityViewType,
  getCommunityViewType,
  updateAdminViewType,
  getAdminViewType,
  updateProjectViewType,
  getProjectViewType,
  updateCommunityDesignViewType,
  getCommunityDesignViewType,
  updateCommunityInstallViewType,
  getCommunityInstallViewType,
  updateCommunityJobViewType,
  getCommunityJobViewType,
  updateCommunityOfficialRequestViewType,
  getCommunityOfficialRequestViewType,
  updateDesignOrderViewType,
  getDesignOrderViewType,
  updateDesignOrderJobViewType,
  getDesignOrderJobViewType,
  updateInstallationViewType,
  getInstallationViewType,
  updateOfficialRequestViewType,
  getOfficialRequestViewType,
  updatePickupViewType,
  getPickupViewType,
  updateProposalViewType,
  getProposalViewType,
  updateQuotationViewType,
  getQuotationViewType,
  updateShippingViewType,
  getShippingViewType,
  updateViewProjectType,
  getViewProjectType,
  updateProjectFilters,
  getProjectFilters,
   deleteProjectFilters,
  getUserPin,
  updateUserPin,
};
