const { TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_WORKSPACE_SID, TWILIO_WORKFLOW_SID, API_URL, TWILIO_API_KEY, TWILIO_API_SECRET, TWILIO_TWIML_APP_SID } = require("../constants/constant");
const {TWILIO_PHONE} = require('../constants/constant')
// const TaskRouter = require("twilio-taskrouter");
const Twilio  = require("twilio")
const Twiml  = require("twilio").twiml
const client = require("twilio")(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
// const VoiceResponse = require('twilio').twiml.VoiceResponse;
const { io } = require('../server');
const { getDepartmentById } = require("../models/department");
const { getActiveCallFlow, addCallRecording, updateCallRecording, addTwilioCalls, getAllCallLogs, getAllSmsList, getCallSettings, updateCallSettings, getAllRecordings, getTotalCalls, totalMissedCalls, getTotalTalkTime, secondsToTime, getAllDepartments, getAgentsByDepartment, getAllCallFlows, addCallFlow, deactivateOtherCallFlow, updateCallFlow, addCallFlowMenu, deleteCallFlowMenu, updateCallSetting, getCallFlowById, updateTwilioConferences,addTwilioSms, getForwardNumberOfAvailableWorker } = require("../models/twilio");
const { default: axios } = require("axios");
const { updateUser } = require("../models/admin");
const sequelize = require("../config/dbconnection");
const Sequelize = require("sequelize");
const { Op } = Sequelize;
const Admin = require ('../models/admin')
const moment = require("moment");
const { empty } = require("../Helpers/Common");
const AccessToken = require('twilio').jwt.AccessToken;
const VoiceGrant = AccessToken.VoiceGrant;
const TaskRouterGrant = AccessToken.TaskRouterGrant;
let DigitPressed = -1
let calledWorkerSid = ''
// const Twiml = require('twilio').twiml;
// const Device = require('twilio-client').Device;

// https://ugrcallcenter.skyniche.website/initiate-call
// +19187165456 - (918) 716-5456
// const workerSid = 'WK8bfb121d767654df6af855d194b90368';

const outgoingCall = async (req, res) => {
  try {
    const { number } = req.query;

    const call = await client.calls.create({
      url: "http://demo.twilio.com/docs/voice.xml",
      to: number,
      from: TWILIO_PHONE,
    });

    if (call.sid) {
      console.log(call.sid);
      res.status(200).send({ message: "Twilio call initiated!" });
    } else {
      res.status(400).send({ message: "Failed to initiate call" });
    }
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const generateWorkerToken = async (req, res) => {
  try {
    const { workerSid, user  } = req.body

    let identity = user
    let worker = {}

    // Fetch Worker details using the Worker SID
    const workerDetails = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID).workers(workerSid).fetch()
    console.log('Worker Identity:', workerDetails.friendlyName);
    identity = workerSid // workerDetails.friendlyName;
    worker = workerDetails
    
      const voiceGrant = new VoiceGrant({
        outgoingApplicationSid: TWILIO_TWIML_APP_SID,
        incomingAllow: true, // Optional: add to allow incoming calls
      });

      const token = new AccessToken(
        TWILIO_ACCOUNT_SID,
        TWILIO_API_KEY,
        TWILIO_API_SECRET,
        {identity: identity}
      );
      token.addGrant(voiceGrant);


      // const capability = new Twilio.jwt.taskrouter.TaskRouterCapability({
      //   accountSid: TWILIO_ACCOUNT_SID,
      //   authToken: TWILIO_AUTH_TOKEN,
      //   workspaceSid: TWILIO_WORKSPACE_SID,
      //   // workerSid: workerSid,
      //   channelId: workerSid,
      // });
    
      const clientToken = token.toJwt()
      console.log("worker ################## ",worker);
      console.log("workerToken ################## ",clientToken);

      const taskRouterGrant = new TaskRouterGrant({
        workerSid: workerSid,
        workspaceSid: TWILIO_WORKSPACE_SID,
        role: "worker",
      });
    
      const accessToken = new AccessToken(
        TWILIO_ACCOUNT_SID,
        TWILIO_API_KEY,
        TWILIO_API_SECRET,
        {identity: identity}
      );
      accessToken.addGrant(taskRouterGrant);

      
      const workerToken = accessToken.toJwt();
      console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^',workerToken);

      if(workerToken) res.status(200).send({ clientToken, workerToken, worker });
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const incomingCall = async (req, res) => {
  try {
    const  data  = req.body
    console.log('88888888888888888888888888888888888888888888888888888888888',data,data.From.includes('client'));
    io?.sockets.emit('customEvent', data);
    // const twiml = new VoiceResponse();
    // twiml.play({}, 'https://demo.twilio.com/docs/classic.mp3');
    const response = new Twiml.VoiceResponse();
    // dial to a twilio client
    // if (false) {
    if (data.From.includes('client')) {
      const callerIdNumber = TWILIO_PHONE;
      const dialOptions = {
        callerId: callerIdNumber,
        action: `${API_URL}/twilio-calls/on-hold`,
      };
  
      if (false) {
        dialOptions.record = 'record-from-ringing-dual';
        dialOptions.recordingStatusCallback = `${API_URL}/twilio-calls/recording-status-callback`;
        dialOptions.recordingStatusCallbackEvent = 'completed';
      }
  
      const dial = response.dial(dialOptions);
      dial.number(`+${data.To || data.phoneNumber}`);
    } else {
      const activeCallFlow = await getActiveCallFlow();

    if (activeCallFlow) {
      const gather = response.gather({ numDigits: '1', action: `${API_URL}/enqueue-call` });

      if (activeCallFlow.welcome_text) {
        gather.say(activeCallFlow.welcome_text);
      }

      let proceed = true;

      if (activeCallFlow.enable_non_working_days === 0 && !(1 <= new Date().getDay() && new Date().getDay() <= 5)) {
        proceed = false;
        gather.say('Please call during working days');
      }

      if (proceed && activeCallFlow.enable_non_working_hours == 0) {
        const currentTime = new Date().toLocaleTimeString('en-US', { hour12: false });
        const startTime = activeCallFlow.start_time || '00:00:00';
        const endTime = activeCallFlow.end_time || '23:59:59';

        if (!(startTime <= currentTime && currentTime <= endTime)) {
          proceed = false;
          gather.say('Please call during office hours');
        }
      }

      if (proceed) {
        if (activeCallFlow.need_menu && activeCallFlow.menu_message) {
          gather.say(activeCallFlow.menu_message);
        }

        if (activeCallFlow.need_menu && activeCallFlow.call_flow_menus) {
          const digitsWord = {
            '1': 'one',
            '2': 'two',
            '3': 'three',
            '4': 'four',
            '5': 'five',
            '6': 'six',
            '7': 'seven',
            '8': 'eight',
            '9': 'nine'
          };

          const playMenu = activeCallFlow.call_flow_menus.map((callFlowMenu) => {
            return `For ${callFlowMenu.department_name} press ${digitsWord[callFlowMenu.press_value]}`;
          });

          gather.say(playMenu.join(', '));
        }
      }
    } else {
      response.say('Unable to connect call');
      response.say('Please try after sometime');
    }
    }

    // Render the response as XML in reply to the webhook request
    res.type('text/xml');
    res.send(response.toString());
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const enqueueCall = async (req, res) => {
  try {
      const response = new Twiml.VoiceResponse();
      const choice = req.body.Digits ? parseInt(req.body.Digits) : -1;
      DigitPressed = choice
      // Mocking the call to the twilio_call_model to get_active_call_flow function
      const activeCallFlow = await getActiveCallFlow();
      const twilioCallSettings = await getCallSettings();
    
      if (activeCallFlow) {
        if (activeCallFlow.need_menu && activeCallFlow.call_flow_menus) {
          const departments = {};
          let wrongInput = true;
    
          activeCallFlow.call_flow_menus.forEach((callFlowMenu) => {
            departments[parseInt(callFlowMenu.press_value)] = `department_${callFlowMenu.department_id}`;
    
            if (parseInt(callFlowMenu.press_value) === choice) {
              wrongInput = false;
            }
          });
    
          if (!wrongInput) {
            const workers = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID).workers.list({activityName: 'Available',})
            console.log('workers------',workers);
            let availableWorker = null
            if(workers?.length > 0){
              availableWorker = workers.filter(worker=>worker.attributes === `{"type":"${departments[choice]}"}`)[0]
              console.log({availableWorker});
            }
            if(availableWorker){
              const callerIdNumber = TWILIO_PHONE;
              const dialOptions = {
                callerId: callerIdNumber,
                action: `${API_URL}/twilio-calls/on-hold`,
              };
              const dial = response.dial(dialOptions);
              calledWorkerSid = availableWorker.sid
              dial.client(availableWorker.sid);
            }else{
            const enqueue = response.enqueue({ workflowSid: TWILIO_WORKFLOW_SID, waitUrl: `${API_URL}/twilio-calls/play-hold-music` });
            enqueue.task(`{"selected_product":"${departments[choice]}"}`);
            }
          } else {
            // response.say('Wrong input');
            response.say(twilioCallSettings?.ON_WRONG_INPUT_MESSAGE);
            const gather = response.gather({ numDigits: '1', action: `${API_URL}/enqueue-call` });
            const digitsWord = {
              '1': 'one',
              '2': 'two',
              '3': 'three',
              '4': 'four',
              '5': 'five',
              '6': 'six',
              '7': 'seven',
              '8': 'eight',
              '9': 'nine'
            };
  
            const playMenu = activeCallFlow.call_flow_menus.map((callFlowMenu) => {
              return `For ${callFlowMenu.department_name} press ${digitsWord[callFlowMenu.press_value]}`;
            });
  
            gather.say(playMenu.join(', '));
          }
        } else {
          response.say('Unable to connect call.');
          response.say('Please try after sometime');
        }
      } else {
        response.say('Unable to connect call.');
        response.say('Please try after sometime');
      }
    
      res.type('text/xml');
      res.send(response.toString());
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const getIncomingCallLogs = async (req, res) => {
  try {
    let callType, startDate, endDate, startTime, endTime, dateString, timestamp, where, whereArray = [];
    callType = req.body && (req.body.values?.callType && req.body.values.callType);
    startDate = req.body && (req.body.values?.startDate && req.body.values.startDate);
    endDate = req.body && (req.body.values?.endDate && req.body.values.endDate);
    startTime = req.body && (req.body.values?.startTime && moment(req.body.values.startTime).format('HH:mm'));
    endTime = req.body && (req.body.values?.endTime && moment(req.body.values.endTime).format('HH:mm'));

		if(callType){
			if(callType === 1){
				whereArray.push({ [Op.or]: [{ call_status: 'completed' }, { call_status: 'in-progress' }] });
			}else if(callType === 2){
        whereArray.push({ [Op.and]: [{ call_status: {[Op.ne]:'completed'} }, { call_status: {[Op.ne]:'in-progress'} }] });
			}
		}

    if(startDate){
      if(startTime){
        dateString = `${startDate} ${startTime}`;
      }else{
        dateString = `${startDate} 00:00:00`;
      }
      timestamp = Math.floor(new Date(dateString).getTime() / 1000);
      whereArray.push({ start_time: { [Op.gte] : timestamp} });
    }

    if(endDate){
      if(endTime){
        dateString = `${endDate} ${endTime}`;
      }else{
        dateString = `${endDate} 23:59:59`;
      }
      timestamp = Math.floor(new Date(dateString).getTime() / 1000);
      whereArray.push({ start_time : { [Op.lte] : timestamp} });
    }

    let data = await getAllCallLogs(whereArray);
    if(data){
      res.send({status:1,message:"Data fetched successfully",result:data})
    }else{
      res.send({status:0,message:"No Data Found"})
    }
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const getTwilioCallSettings = async (req, res) => {
  try {
    // const { phone } = req.body;
    let data = await getCallSettings();
    res.send({status:1,message:"Data fetched successfully",result:data})
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const getCallFlowDataById = async (req, res) => {
  let { callFlowId } = req.body;
  let data={};
  data['call_flow'] = await getCallFlowById(callFlowId);
	data['departments'] = await getAllDepartments();
  return data;
}

const updateTwilioCallSettings = async (req, res) => {
  try {
    const callSettings = {
      TWILIO_ACCOUNT_SID: req.body.account_sid,
      TWILIO_AUTH_TOKEN: req.body.auth_tocken,
      TWILIO_TWIML_APP_SID: req.body.application_sid,
      TWILIO_WORKSPACE_SID: req.body.workspace_sid,
      TWILIO_WORKFLOW_SID: req.body.workflow_sid,
      TWILIO_FORWARD_PHONE: req.body.call_forward_number && String(req.body.call_forward_number).replace(/[^0-9]/g, ''),
    };
    // console.log({callSettings});
    let data = await updateCallSettings(callSettings);
    res.send({status:1,message:"Data fetched successfully",result:data})
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: "Server error" });
  }
};

const smsLogs = async (req,res) => {
  try{
    let smsType, startDate, endDate, startTime, endTime, dateString, timestamp, where, whereArray = [];
    smsType = req.body && req.body.values && (req.body.values.smsType && req.body.values.smsType);
    startDate = req.body && req.body.values && (req.body.values.startDate && req.body.values.startDate);
    endDate = req.body && req.body.values && (req.body.values.endDate && req.body.values.endDate);
    startTime = req.body && req.body.values && (req.body.values.startTime && moment(req.body.values.startTime).format('HH:mm'));
    endTime = req.body && req.body.values && (req.body.values.endTime && moment(req.body.values.endTime).format('HH:mm'));
    const phone = req.body ? req.body.phone : null
    let whereCondition=""
    if(smsType){
      if(smsType === 1){
         whereArray.push({ direction : 'outbound-api' });
        whereCondition+=" and direction='outbound-api'"
      }else if(smsType === 2){
        whereArray.push({ direction: { [Op.not]: 'outbound-api' } });
        whereCondition+=" and direction!='outbound-api'"
      }
    }

    if(startDate){
      if(startTime){
        dateString = `${startDate} ${startTime}`;
      }else{
        dateString = `${startDate} 00:00:00`;
      }
      timestamp = Math.floor(new Date(dateString).getTime() / 1000);
      if(!empty(whereCondition)){
        whereCondition+=" and date_created>="+timestamp
      }
      else{
        whereCondition+="  date_created>="+timestamp
      }
      whereArray.push({ date_created : { [Op.gte] : timestamp} });
    }
      
    if(endDate){
      if(endTime){		
        dateString = `${endDate} ${endTime}`;
      }else{
        dateString = `${endDate} 23:59:59`;
      }
      timestamp = Math.floor(new Date(dateString).getTime() / 1000);
      whereArray.push({ date_created : { [Op.lte] : timestamp} });	
      if(!empty(whereCondition)){
        whereCondition+=" and date_created<="+timestamp
      }
      else{
        whereCondition+="  date_created<="+timestamp
      }		
    }
    let sortedList = []
    const smsList = await getAllSmsList(whereCondition);
    if(phone){
      const inboundMsgs = await client.messages.list({from:phone})
      sortedList = [...smsList,...inboundMsgs.map(msg=>{
        return {
          isFetched:true,
          direction: msg.direction,
          date_created: moment(msg.dateCreated).valueOf(),
          date_updated: moment(msg.dateupdateUpdated).valueOf(),
          message_body:msg.body,
          to:msg.to,
          sms_status:msg.status,
          id:msg.sid,
          price:msg.price,
          price_unit:msg.priceUnit,
        }
      })]
    }else{
      sortedList = smsList
    }
    res.send({status:1,message:"Data fetched successfully",result:sortedList})
  }
  catch(error){
    console.log("smsLogs error",error)
    res.send({status:0,message:"Error fetching data"})
  }
}

const downloadRecording = async(recordingUrl)=> {
  // Your logic to download the recording content
  const response = await axios.get(recordingUrl, { responseType: 'arraybuffer' });
  return new Promise((resolve) => {
    setTimeout(() => {
      const recordingContent = Buffer.from(response.data, 'binary'); // utf-8
      resolve(recordingContent);
    }, 1000);
  });
}

const onHold = async(req,res)=> {
  const dialCallStatus = req.body.DialCallStatus;
  const dialledFrom = req.body.From;
  console.log('dialledFrom---',dialledFrom);
  const isOutgoingCall = (dialledFrom?.startsWith('client:')) ? true : false
  console.log('isOutgoingCall---',isOutgoingCall);
  console.log('////////////////////////////////////////////////////',req.body);

  const response = new Twiml.VoiceResponse();
  if((isOutgoingCall) && (['no-answer', 'failed', 'busy', 'canceled'].includes(dialCallStatus))){
    response.say('The number you have called is busy right now! Please call after some time.');
    response.reject();
  } else if((isOutgoingCall) && (['completed'].includes(dialCallStatus))){
    response.reject();
  } else if (['no-answer', 'failed'].includes(dialCallStatus)) {
    response.say('Please hold while we forward your call to the live agent.');
    response.redirect('/twilio-calls/forward-when-not-answered');
  } else if (['busy', 'failed', 'canceled'].includes(dialCallStatus)) {
    response.say('Sorry! Please call after some time.');
    response.reject();
  } else if (['completed'].includes(dialCallStatus)) {
    response.reject();
  } else {
    response.say('You have a caller on hold.');
    response.redirect('/twilio-calls/on-hold');
  }

  res.type('text/xml');
  res.send(response.toString());
}

const playHoldMusic  = async(req,res)=> {
  const response = new Twiml.VoiceResponse();
  
  const musicOnHoldUrl = 'http://com.twilio.sounds.music.s3.amazonaws.com/MARKOVICHAMP-Borghestral.mp3';
  response.play(musicOnHoldUrl, { loop: 0 });

  res.type('text/xml');
  res.send(response.toString());
}

const createCallForRecording = async(callSid, conferenceSid) => {
  try {
    const call = await client.calls(callSid).fetch();

    const participant = {
      to: call.to,
      from: call.from,
      forwardedFrom: call.forwardedFrom,
      direction: call.direction,
      duration: call.duration,
      startTime: call.startTime.toISOString(),
      endTime: call.endTime.toISOString(),
      groupSid: call.groupSid,
      parentCallSid: call.parentCallSid,
      phoneNumberSid: call.phoneNumberSid,
      price: parseFloat(call.price),
      priceUnit: call.priceUnit,
      sid: call.sid,
      callStatus: call.status,
      dateCreated: call.dateCreated.toISOString(),
      dateUpdated: call.dateUpdated.toISOString(),
    };

    if (conferenceSid) {
      participant.conferenceSid = conferenceSid;
    }
    const dataId = await addTwilioCalls(participant);

    console.log('Participant added successfully. Data ID:', dataId);
  } catch (error) {
    console.error('Error creating call for recording:', error);
    throw error;
  }
}

const recordingStatusCallback = async (req, res) => {
  try {
      const callRecording = {
        callSid: req.body.CallSid || '',
        conferenceSid: req.body.ConferenceSid || '',
        recordingSid: req.body.RecordingSid,
        recordingUrl: req.body.RecordingUrl,
        recordingStatus: req.body.RecordingStatus,
        recordingDuration: req.body.RecordingDuration,
        recordingChannels: req.body.RecordingChannels,
        recordingStartTime: new Date(req.body.RecordingStartTime),
        recordingSource: req.body.RecordingSource,
      };
  
      const callRecordingId = await addCallRecording(callRecording);
  
      if (callRecording.recordingUrl) {
        const recordingContent = await downloadRecording(callRecording.recordingUrl);
        const finalFileName = callRecording.recordingUrl.split('/').pop() + '.mp3';
  
        fs.writeFileSync(`downloads/call-recordings/${finalFileName}`, recordingContent);
  
        const callRecordingUpdate = {
          localFileName: finalFileName,
          downloaded: 1,
        };
  
        if (callRecordingId) {
          await updateCallRecording(callRecordingId, callRecordingUpdate);
        }
      }
  
      if (!callRecording.callSid) {
        const recording = await client.recordings(callRecording.recordingSid).fetch();
  
        if (callRecordingId) {
          await updateCallRecording(callRecordingId, { callSid: recording.callSid });
        }
  
        await createCallForRecording(recording.callSid, recording.conferenceSid);
      }
  
      res.sendStatus(200);
    } catch (error) {
      console.error('Error handling recording status callback:', error);
      res.status(500).send('Internal Server Error');
    }
};

const updateAvailableForCall = async (req, res) => {
  try {
    const { userId, availableForCall, workerSid, activityName } = req.body;

    const activities = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID).activities.list()
    const activity = {};

    activities.forEach(record => {
      activity[record.friendlyName] = record.sid;
    });

    console.log('*******************************************', activity,{activityName});

    // Update the user in the database
    const updatedUser = await updateUser(userId, { available_for_call:availableForCall });
    const updatedWorker = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID)
      .workers(workerSid)
      .update({
        activitySid: activity[activityName],
      })
    if(updatedWorker){
      console.log(`Successfully updated worker's activity to ${activityName}: ${updatedWorker.friendlyName}`);
    }
    if (updatedUser && updatedWorker) {
      res.status(200).send({ status: 1, message: `Successfully updated worker's activity to ${activityName}` });
    }else if(updatedUser){
      res.status(500).send({ status: 0, message: `error in updating worker` });
    }else{
      res.status(500).send({ status: 0, message: `error in updating user in database` });
    }
    
  } catch (error) {
    console.error('Error updating available_for_call:', error);
    res.status(500).json(json);
  }
};

async function createTwilioSupportWorker(user_id, worker_name, department_id = 2) {
  let department_name = "department_2";

  // Fetch department information from the database
  const department = await getDepartmentById(department_id);
  console.log('department---',department);
  if (department) {
    department_name = `department_${department[0].id}`;
  }

  // Check if the worker already exists
  let worker;
  try {
    worker = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID)
      .workers
      .list({
        friendlyName: worker_name
      });
  } catch (error) {
    console.error('Error fetching worker:', error);
  }

  let workerSid;
  if (worker && worker.length > 0) {
    workerSid = worker[0].sid;
  } else {
    // Create a new worker if not found
    try {
      const newWorker = await client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID)
        .workers
        .create({
          friendlyName: worker_name,
          attributes: JSON.stringify({
            type: department_name
          })
        });

      workerSid = newWorker.sid;
    } catch (error) {
      console.error('Error creating worker:', error);
      return 0;
    }
  }
  // Update user in the database with worker_sid
  const user = await updateUser(user_id, { worker_sid: workerSid });
  if(user){
    return workerSid;
  }else {
    return 0;
  }
}

const getAllRecordingsList = async (req,res) => {
  try{
    let callRecordings = await getAllRecordings();
    res.send({status:1,message:"Data fetched successfully",result:callRecordings})
  }
  catch(error){
    console.log(error);
    res.send({status:0,message:"Error fetching recordings",error:error})
  }
}

const getAnalyticsData = async (req,res) => {
  try{
    const data = {
      total_inbound_calls: await getTotalCalls('inbound', null),
      total_outbound_calls: await getTotalCalls('outbound-dial', null),
      total_missed_calls: await totalMissedCalls(),
      total_answered_calls: parseInt(await getTotalCalls(null, "(call_status='completed' OR call_status='in-progress')")),
  
      total_inbound_talk_time: await getTotalTalkTime('inbound'),
      total_outbound_talk_time: await getTotalTalkTime('outbound-dial'),
    };

    const totalInboundTalkTimeSeconds = data.total_inbound_talk_time.seconds;
    const totalOutboundTalkTimeSeconds = data.total_outbound_talk_time.seconds;
    const totalTalkTime = totalInboundTalkTimeSeconds + totalOutboundTalkTimeSeconds;
    const totalCalls = data.total_missed_calls + data.total_answered_calls;

    let averageHandleTime = 0;
    let totalHandleTime = '';

    if (totalCalls !== 0) {
      averageHandleTime = totalTalkTime / totalCalls;

      const totalHandleTimeArray = secondsToTime(averageHandleTime);

      if (totalHandleTimeArray.d) {
        totalHandleTime += totalHandleTimeArray.d + 'd';
      }
      if (totalHandleTimeArray.h) {
        totalHandleTime += totalHandleTimeArray.h + 'h ';
      }
      if (totalHandleTimeArray.m) {
        totalHandleTime += totalHandleTimeArray.m + 'm ';
      }
      if (totalHandleTimeArray.s) {
        totalHandleTime += totalHandleTimeArray.s + 's';
      }

      data.average_handle_time = totalHandleTime;
      data.rate_of_answered_calls = (data.total_answered_calls / totalCalls).toFixed(2);
    } else {
      data.rate_of_answered_calls = 0;
      data.average_handle_time = 0;
    }
    data.total_inbound_talk_time = (data.total_inbound_talk_time.text == '') ? '0s' : data.total_inbound_talk_time.text
    data.total_outbound_talk_time = (data.total_outbound_talk_time.text == '') ? '0s' : data.total_outbound_talk_time.text

    const chartData = {}

    for (let i = 6; i >= 0; i--) {
      const weekEnd = new Date(Date.now() - i * 24 * 60 * 60 * 1000);
      const formattedWeekEnd = formatDate(weekEnd);
  
      chartData[formattedWeekEnd] = {
        totalInboundCalls: await getTotalCalls('inbound', null, weekEnd),
        totalOutboundCalls: await getTotalCalls('outbound-dial', null, weekEnd),
        totalMissedCalls: await totalMissedCalls(weekEnd),
        totalAnsweredCalls: await getTotalCalls(
          null,
          "(call_status='completed' OR call_status='in-progress')",
          weekEnd
        ),
      };
    }

    // data.chartData = chartData;
    res.send({status:1,message:"Data fetched successfully",result:data,chartData})
  }
  catch(error){
    console.log(error);
    res.send({status:0,message:"Error fetching recordings",error:error})
  }
}

const formatDate = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

const imTasks = async (req,res) => {
  try{
    let departmentId,userId;
    let data = {};
    data['departments'] = await getAllDepartments();
    // if(req.body){
      // departmentId = req.body.departmentId && req.body.departmentId
      userId = req.body.userId && req.body.userId
      data['agents'] = await getAgentsByDepartment(departmentId,userId);
    // }
    res.send({status:1,message:"Data fetched successfully",result:data});
  }
  catch(error){
    console.log(error);
    res.send({status:0,message:"Error fetching data",error:error});
  }
}

const callFlows = async (req,res) => {		
  try{
    let data = {};
    data['call_flows'] = await getAllCallFlows();
    data['departments'] = await getAllDepartments();
    data['call_settings'] = await getCallSettings();
    return data;
  }catch(error){
    console.log("error : ",error);
  }
}

const createCallFlow = async (request,reply) => {
  try{
    let callFlow = {};
    let currentDate = Math.round(moment().valueOf() / 1000);
    callFlow['welcome_text']= request.body.welcomeText;
    callFlow['need_menu']=parseInt(request.body.needMenu);
    if(callFlow['need_menu']){
      callFlow['menu_message']=request.body.menuMessage;				
    }
    callFlow['enable_non_working_hours']=parseInt(request.body.enableNonWorkingHours);
    callFlow['enable_non_working_days']=parseInt(request.body.enableNonWorkingDays);
    if(request.body.startDay){
      callFlow['start_day']=request.body.startDay;
    }
    if(request.body.endDay){
      callFlow['end_day']=request.body.endDay;
    }
    if(request.body.startTime){
      callFlow['start_time']=request.body.startTime;
    }
    if(request.body.endTime){
      callFlow['end_time']=request.body.endTime;
    }
    callFlow['timestamp']=currentDate;
    callFlow['added_by']=request.body.userId;
    callFlow['status']=1;
    
    let callFlowId = await addCallFlow(callFlow);	
    if(callFlowId){
      await deactivateOtherCallFlow();
      let callFlowStatus = {};
      callFlowStatus['status']=1;
      let updated = await updateCallFlow(callFlowId,callFlowStatus);
  
      if(callFlow['need_menu']){
        let pressValues = request.body.pressValue;
      
        // let pressValues = request.body.values.pressValue;
        // let departmentIds = request.body.values.departmentId;
        for (let i=0; i < pressValues.length ; i++) {
         
          let callFlowMenu = {};
          callFlowMenu['twilio_call_flow_id'] = callFlowId;
          callFlowMenu['press_value'] = pressValues[i].press_value;
          callFlowMenu['department_id'] = pressValues[i].department;
          await addCallFlowMenu(callFlowMenu);	
        }
      }
      // Notification
      let notificationMsg="New call flow has been created.";				
      let notificationUrl="call-center/call-flows";				

      // Alert to user of new added call flow
      const incrementResult_User = await Admin.incrementField(callFlow['added_by'],"noti_count",1);
      let notificationData_user = {
          user_id: callFlow['added_by'],
          url: notificationUrl,
          timestamp: currentDate,
          message: notificationMsg,
          status: 1,
          from_id: callFlow['added_by'],
      };
      const addNotificationResult_user = await Admin.addNotification(notificationData_user);
      // Alert to admins of new added call flow
      let adminIds = await Admin.getAllAdminIds();
      let notificationData = {};
      for (const adminId of adminIds) {
        if (adminId != callFlow['added_by']) {
          const incrementResult = await Admin.incrementField(adminId,"noti_count",1);
          notificationData = {
            user_id: adminId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: callFlow['added_by'],
          };
          const addNotificationResult = await Admin.addNotification(notificationData);
        }
      }
      reply.send({status:1, message:'Call flow has been successfully created!'});
    }else{
      reply.send({status:0, message:'Failed to create call flow!'});
    }
  }catch(error){
    console.log("error : ",error);
  }
}

const editCallFlow = async (request,reply) => {
  try{
    let {callFlowId,userId} = request.body;
    let currentDate = Math.round(moment().valueOf() / 1000);
    let callFlow = {};
    callFlow['welcome_text']= request.body.welcomeText;
    callFlow['need_menu']=parseInt(request.body.needMenu);
    if(callFlow['need_menu']){
      callFlow['menu_message']=request.body.menuMessage;				
    }
    callFlow['enable_non_working_hours']=parseInt(request.body.enableNonWorkingHours);
    callFlow['enable_non_working_days']=parseInt(request.body.enableNonWorkingDays);
    if(request.body.startDay){
      callFlow['start_day']=request.body.startDay;
    }
    if(request.body.endDay){
      callFlow['end_day']=request.body.endDay;
    }
    if(request.body.startTime){
      callFlow['start_time']=request.body.startTime;
    }
    if(request.body.endTime){
      callFlow['end_time']=request.body.endTime;
    }
    let updated = await updateCallFlow(callFlowId,callFlow);
    await deleteCallFlowMenu(callFlowId);

    if(callFlow['need_menu']){
      let pressValues = request.body.pressValue;
      // let departmentIds = request.body.values.departmentId;
      let callFlowMenuId;
      for (let i=0; i < pressValues.length ; i++) {
        let callFlowMenu = {};
        callFlowMenu['twilio_call_flow_id'] = callFlowId;
        callFlowMenu['press_value'] = pressValues[i].press_value;
        callFlowMenu['department_id'] = pressValues[i].department;
        callFlowMenuId = await addCallFlowMenu(callFlowMenu);
      }
    }
    if(updated || callFlowMenuId){
      // Notification
      let notificationMsg = "The call flow has been updated.";				
      let notificationUrl = "call-center/call-flows";				
      // Alert to user of updated call flow
      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);
      // Alert to admins of updated call flow
      let adminIds = await Admin.getAllAdminIds();
      let notificationData = {};
      for (const adminId of adminIds) {
        if (adminId != userId) {
          const incrementResult = await Admin.incrementField(adminId,"noti_count",1);
          notificationData = {
            user_id: adminId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId,
          };
          const addNotificationResult = await Admin.addNotification(notificationData);
        }
      }
      reply.send({status:1, message:'Call flow has been successfully updated!'});
    }else{
      reply.send({status:0, message:'Failed to update call flow!'});
    }
  }catch(error){
    console.log("error : ",error);
  }
}

const activateCallFlow = async (request,reply) => {
  try{
    let { callFlowId, userId } = request.body;
    let currentDate = Math.round(moment().valueOf() / 1000);
    let callFlow = {};
    await deactivateOtherCallFlow();
    callFlow['status']=1;
    let updated = await updateCallFlow(callFlowId,callFlow);
    if(updated){				
      // Notification
      let notificationMsg="The call flow has been activated.";				
      let notificationUrl="call-center/call-flows";				
      // Alert to user of call flow activation
      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);
      // Alert to admins of call flow activation
      let adminIds = await Admin.getAllAdminIds();
      let notificationData = {};
      for (const adminId of adminIds) {
        if (adminId != userId) {
          const incrementResult = await Admin.incrementField(adminId,"noti_count",1);
          notificationData = {
            user_id: adminId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId,
          };
          const addNotificationResult = await Admin.addNotification(notificationData);
        }
      }
      reply.send({status:1, message:'Call flow has been successfully activated!'});
    }else{
      reply.send({status:0, message:'Failed to activate call flow!'});
    }
  }catch(error){
    console.log("error : ",error);
  }
}

const deleteCallFlow = async (request,reply) => {
  try{
    let { callFlowId, userId } = request.body;
    let currentDate = Math.round(moment().valueOf() / 1000);
    let callFlow = {};
    callFlow['status']=2;
    let updated = await updateCallFlow(callFlowId,callFlow);
    if(updated){				
    // Notification
    let notificationMsg = "The call flow has been deleted.";				
    let notificationUrl = "call-center/call-flows";				
    // Alert to user of deleted call flow
      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);
      // Alert to admins of deleted call flow
      let adminIds = await Admin.getAllAdminIds();
      let notificationData = {};
      for (const adminId of adminIds) {
        if (adminId != userId) {
          const incrementResult = await Admin.incrementField(adminId,"noti_count",1);
          notificationData = {
            user_id: adminId,
            url: notificationUrl,
            timestamp: currentDate,
            message: notificationMsg,
            status: 1,
            from_id: userId,
          };
          const addNotificationResult = await Admin.addNotification(notificationData);
        }
      }
      reply.send({status:1, message:'Call flow has been successfully deleted!'});
    }else{
      reply.send({status:0, message:'Failed to delete call flow!'});
    }
  }catch(error){
    console.log("error : ",error);
  }
}

const advanceCallFlowSettings = async (request,reply) => {
  try{
    let callSettings={};
    callSettings['MENU_REPEAT_COUNT']=request.body.menuRepeatCount;
    callSettings['ON_WRONG_INPUT_MESSAGE']=request.body.onWrongInputMessage;
    callSettings['CALL_RECORDING']=request.body.callRecording;
    callSettings['MUSIC_ON_HOLD']=request.body.audioFileName;				

    // if(count($_FILES['MUSIC_ON_HOLD']['name'])>=1 && !empty($_FILES['MUSIC_ON_HOLD']['name'][0])){
    //   let uploaded=$this->twilio_call_model->do_upload('MUSIC_ON_HOLD');
    //     if(isset($uploaded['error'])){
    //       $this->session->set_flashdata('error_msg', $uploaded['error']);
    //       redirect('call-center/call-flows');
    //     }else{
    //       if($uploaded['file_name']!='') {		
    //         $call_settings['MUSIC_ON_HOLD']=$uploaded['file_name'];						
    //       }
    //     }
    //   }

    for (const name in callSettings) {
      if (callSettings.hasOwnProperty(name)) {
        const value = callSettings[name];
        
        await updateCallSetting(name, { value: value });
      }
    }
    reply.send({status:1,message:'Advance call flow settings has been successfully updated!'});
  }
  catch(error){
    console.log("error",error);
    reply.send({status:0,message:'Failed to update advance call flow settings!'});
  }
}

const callForwarding = async (req,res) => {
  try{
    const activeCallFlow = await getActiveCallFlow();
    const data = await getCallSettings();
    const response = new Twiml.VoiceResponse();
    // activeCallFlow.call_flow_menus.find(menu=>menu.press_value===DigitPressed)?.forward_number || 
    const phoneNumberToDial =  data?.TWILIO_FORWARD_PHONE // '14173892684'
    if (phoneNumberToDial) {
      const dial = response.dial();
      dial.number(
      //   { 
      //   statusCallbackEvent: 'initiated ringing answered completed',
      //   statusCallback: 'your_status_callback_url', // Replace with your actual status callback URL
      // }, 
      `+${phoneNumberToDial}`);
    }
    res.type('text/xml');
    res.send(response.toString());
  } catch(error){
    console.log(error);
    res.send({status:0,message:"Error fetching data",error:error});
  }
}

const callForwardingWhenNotAnswered = async (req,res) => {
  try{
    console.log('calledWorkerSid--',calledWorkerSid);
    const activeCallFlow = await getForwardNumberOfAvailableWorker(calledWorkerSid);
    console.log('activeCallFlow----',activeCallFlow);
    const response = new Twiml.VoiceResponse();
    const phoneNumberToDial =  activeCallFlow?.call_flow_menus?.find(menu=>menu?.press_value===DigitPressed)?.forward_no || response.say('Sorry! No agents are available right now. Please call after some time'); // 14173892684
    if (phoneNumberToDial) {
      const dial = response.dial();
      dial.number(`+${phoneNumberToDial}`);
    }else{
      response.say('Sorry! No agents are available right now. Please call after some time');
    }
    res.type('text/xml');
    res.send(response.toString());
  }
  catch(error){
    console.log(error);
    res.send({status:0,message:"Error fetching data",error:error});
  }
}

const getUserById = async (req,res) => {
  try{
    const {userId} = req.body
    const result = await Admin.getUserById(userId);
    return result;
  }
  catch(error){
    console.log(error);
  }
}

const acceptReservation = async (req,res) => {
  try{
    const {taskSid,reservationSid} = req.body
    client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID).tasks(taskSid).reservations(reservationSid).update({reservationStatus: 'accepted'}).then((res)=>{
      console.log('reservation accepted ',res);
    })
  }
  catch(error){
    console.log(error);
  }
}

const makeReservationConference = async (req,res) => {
  try{
    const {taskSid,reservationSid} = req.body
    client.taskrouter.v1.workspaces(TWILIO_WORKSPACE_SID)
    .tasks(taskSid)
    .reservations(reservationSid)
    .update({
      instruction: 'conference',
      statusCallback: 'https://www.example.com/ConferenceEvents',
      conferenceStatusCallbackEvent: ['start', 'end', 'join', 'leave', 'mute', 'hold']
    }).then((res)=>{
      console.log('reservation conference ',res);
    })
  }
  catch(error){
    console.log(error);
  }
}

const conferenceStatusCallback = async (req,res) => {
  const conferenceSid = req.body.conferenceSid;
  console.log("conferenceSid",conferenceSid);
  try {
    const conferenceData = await client.conferences(conferenceSid).fetch();
    console.log("conferenceData",conferenceData);
    if (conferenceData) {
      const data = {
        friendly_name: conferenceData.friendlyName,
      };

      if (conferenceData.reasonConferenceEnded) {
        data.reason_conference_ended = conferenceData.reasonConferenceEnded;
      }

      if (conferenceData.callSidEndingConference) {
        data.call_sid_ending_conference = conferenceData.callSidEndingConference;
      }

      data.sid = conferenceData.sid;
      data.call_status = conferenceData.status;
      data.date_created = new Date(conferenceData.dateCreated).getTime() / 1000;
      data.date_updated = new Date(conferenceData.dateUpdated).getTime() / 1000;

      // Assuming you have a function updateTwilioConferences in a separate module
      const updatedData = await updateTwilioConferences(conferenceSid, data);
      console.log("updatedData",updatedData);
      if (data.call_status === 'completed') {
        // const participants = await client.conferences(conferenceSid)
        //   .participants
        //   .list();
      }
    }

    if (req.body.StatusCallbackEvent === 'participant-leave' || req.body.StatusCallbackEvent === 'participant-speech-stop') {
      const participants = await client.conferences(conferenceSid)
        .participants
        .list();
      console.log("participants",participants);
      if (participants && participants.length <= 1) {
        const updatedConference = await client.conferences(conferenceSid)
          .update({ status: 'completed' });

        console.log("updatedConference.friendlyName",updatedConference.friendlyName);
      }
    } else {
      res.send('');
    }
    res.status(200).send({status:1});
  } catch (error) {
    console.error('Error:', error.message);
    res.status(500).send('Internal Server Error');
  }
}

const assignmentCallback = (req,res) => {

  console.log('=================================================================',req);
  const callerIdNumber = TWILIO_PHONE;
      const dialOptions = {
        callerId: callerIdNumber,
        action: `${API_URL}/twilio-calls/on-hold`,
      };

  assignmentInstruction = {
    'instruction' : 'dequeue',
    'post_work_TWILIO_ACTIVITY_SID' : 'WA2e4dd266d132ea32861e3aeda6f3ecff',
    'from' : TWILIO_PHONE,
    'to' : 'client:WK8bfb121d767654df6af855d194b90368',
  };

  // res.type('application/json');
  // res.send(JSON.stringify(assignmentInstruction));

  // <Dial>
  //       <Conference endConferenceOnExit="true">YourReservationSid</Conference>
  //   </Dial>

  const response = new Twiml.VoiceResponse();
  const dial = response.dial(dialOptions);
  dial.client(`WK8bfb121d767654df6af855d194b90368`);
  res.type('text/xml');
  res.send(response.toString());
}

const initiateMessage = async (req,res) => {
  try{
    const messageData  = req.body;
    let data = {};
    let messageSid;
    // console.log("Messaging data---------",messageData);
    if(messageData.messageContents){
      const message = await client.messages.create({
        body: messageData.messageContents,
        to: messageData.phoneNumber,
        from: TWILIO_PHONE,
      });
      messageSid = message.sid;
    }
    else{
      messageSid = messageData.MessageSid;
      const twiml = new Twiml.MessagingResponse();
      res.type('text/xml');
      res.send(twiml.toString());
    }
    if(messageSid){
      const messages = await client.messages(messageSid).fetch();
      // console.log("messagesssssssssssssssssssss",messages);
      data['partner_id'] = messageData.partner_id && messageData.partner_id;
      data['contact_id'] = messageData.contact_id && messageData.contact_id;	
      data['lead_id'] = messageData.lead_id && messageData.lead_id;
      data['user_id'] = messageData.userId;
      data['from'] = messages.from;
      data['to'] = messages.to;
      data['message_body'] = messages.body;
      data['direction'] = messages.direction;
      data['price'] = messages.price && parseInt(messages.price) || 0;
      data['price_unit'] = messages.priceUnit;
      data['sid'] = messages.sid;
      data['sms_status'] = messages.status;
      data['date_created'] = Math.floor(new Date(messages.dateCreated).getTime() / 1000);
      data['date_updated'] = Math.floor(new Date(messages.dateUpdated).getTime() / 1000);
      
      let dataUpdated = await addTwilioSms(data);
      if(dataUpdated){
        res.status(200).send({ message: "Message updated successfully!"});
      }
    }
  }
  catch(error){
    res.status(500).send({ message: "Error updating message!"});
    console.log("Message error",error);
  }
}

const incomingMessage = async (req, res) => {
  const { From, Body } = req.body;
  let messageLogs = [];
  const newMessage = { from: From, body: Body };
  messageLogs.push(newMessage);

  console.log('New message received : ', newMessage);

  const twiml = new Twiml.MessagingResponse();
  res.writeHead(200, { 'Content-Type': 'text/xml' });
  res.end(twiml.toString());
}

const addOutgoingCallDetailsAjax = async (req,res) => {
  try{
    if(req.body){
      const parentCallSid = req.body.callSid;
      // const fromCallerId = From;
      // const prefix = 'client:';
      // const dialedFrom = fromCallerId.slice(prefix.length);
      // console.log("parentCallSid-----",parentCallSid);
      if(parentCallSid){
        const calls = await client.calls.list({ parentCallSid });
        const call = calls[0];
        // console.log("call----------------------",call);
        if(call){
          let data = {};
          data['to'] = call.to;
          data['from'] = call.from;
          data['forwarded_from'] = call.forwardedFrom;
          data['direction'] = call.direction;
          data['duration'] = call.duration;
          data['start_time'] = Math.floor(new Date(call.startTime).getTime() / 1000);
          data['end_time'] = Math.floor(new Date(call.endTime).getTime() / 1000);
          data['group_sid'] = call.groupSid;
          data['parent_call_sid'] = call.parentCallSid;
          data['phone_number_sid'] = call.phoneNumberSid;
          data['price'] = call.price && parseInt(call.price) || 0;
          data['price_unit'] = call.priceUnit;
          data['sid'] = call.sid;
          data['call_status'] = call.status;
          data['date_created'] = Math.floor(new Date(call.dateCreated).getTime() / 1000);
          data['date_updated'] = Math.floor(new Date(call.dateUpdated).getTime() / 1000);
          
          if(call.direction=='outbound' || call.direction=='outbound-api' || call.direction=='outbound-dial'){
            data['from_user_id'] = req.body.fromUserId || null;
            data['to_user_id'] = req.body.toUserId || null;
          }else{
            data['to_user_id'] = req.body.toUserId || null;
            data['from_user_id'] = req.body.fromUserId || null;
          }
                    
          let data_id = await addTwilioCalls(data);
          if(data_id){
            res.send({status:1,message:"Call details saved successfully"})
          }
        }
      }
    }else{
      res.send({status:0,message:"Failed to save Call details"})
    }
  }
  catch(error){
    console.log("Add calls to twilio error",error);
    res.send({status:500,message:"Error saving call details"})
  }
}

const getIncomingCallNumber = async (req,res) => {
  try{
    const {callSid} = req.body;
    // const callSid = "CA31665086fefe5fbd53a3b9c2f0578a1e";
    const call = await client.calls(callSid).fetch();
    console.log("call--parentCallSid---",call.parentCallSid);
    const callId = call.parentCallSid
    const parentCall = await client.calls(callId).fetch();
    console.log("parentCall--from---",parentCall.from);
    res.send({ status:1, number:parentCall.from, details:parentCall })
  }
  catch(error){
    console.log("getIncomingCallNumber error : ",error);
  }
}

const addIncomingCallDetails = async (req,res) => {
  try{
    if(req.body){
      const parentCall = req.body.parentCall;
      const childSid = req.body.childSid;
      if(childSid){
        const call = await client.calls(childSid).fetch();
        if(call){
          let data = {};
          data['to'] = call.to;
          data['from'] = parentCall.from;
          data['forwarded_from'] = call.forwardedFrom;
          data['direction'] = parentCall.direction;
          data['duration'] = call.duration;
          data['start_time'] = Math.floor(new Date(parentCall.startTime).getTime() / 1000);
          data['end_time'] = Math.floor(new Date(call.endTime).getTime() / 1000);
          data['group_sid'] = call.groupSid;
          data['parent_call_sid'] = call.parentCallSid;
          data['phone_number_sid'] = call.phoneNumberSid;
          data['price'] = call.price && parseInt(call.price) || 0;
          data['price_unit'] = call.priceUnit;
          data['sid'] = call.sid;
          data['call_status'] = call.status;
          data['date_created'] = Math.floor(new Date(parentCall.dateCreated).getTime() / 1000);
          data['date_updated'] = Math.floor(new Date(call.dateUpdated).getTime() / 1000);
          data['from_user_id'] = req.body && (req.body.fromUserId ? req.body.fromUserId : null) || null;
          data['to_user_id'] = req.body && (req.body.toUserId ? req.body.toUserId : null) || null;

          let result = await addTwilioCalls(data);
          if(result){
            res.send({status:1,message:"Call details saved successfully",parentCall:parentCall,childSid:childSid})
          }
        }
      }
    }else{
      res.send({status:0,message:"Failed to save Call details"})
    }
  }
  catch(error){
    console.log("Add calls to twilio error",error);
    res.send({status:500,message:"Error saving call details"})
  }
}

const scanCrmPhoneNumber = async (req,res) => {
  try{
    let {phoneNumber} = req.body;
    phoneNumber = phoneNumber.replace('+', '');
    const existenceResult = await Admin.scanCrmPhoneNumber(phoneNumber);
    if(existenceResult){
      res.send({status:1,message:"Phone number details detched successfully",existenceResult:existenceResult});
    }else{
      res.send({status:0,message:"Number not exists"});
    }
  }
  catch(error){
    console.log("scanCrmPhoneNumber error",error);
  }
}

module.exports = {
  outgoingCall,
  incomingCall,
  enqueueCall,
  generateWorkerToken,
  createTwilioSupportWorker,
  recordingStatusCallback,
  onHold,
  playHoldMusic,
  getIncomingCallLogs,
  updateAvailableForCall,
  smsLogs,
  getAllRecordingsList,
  getTwilioCallSettings,
  updateTwilioCallSettings,
  getAnalyticsData,
  imTasks,
  callForwarding,
  callFlows,
  createCallFlow,
  editCallFlow,
  activateCallFlow,
  deleteCallFlow,
  advanceCallFlowSettings,
  getCallFlowDataById,
  getUserById,
  acceptReservation,
  conferenceStatusCallback,
  assignmentCallback,
  initiateMessage,
  incomingMessage,
  addOutgoingCallDetailsAjax,
  getIncomingCallNumber,
  addIncomingCallDetails,
  scanCrmPhoneNumber,
  callForwardingWhenNotAnswered,
 };
