const entity = $db.entity({ version: "v1" });
const AuomergerPayload = entity.get("newRulePloadDB2");
const nodemailer = require("nodemailer");
const transporter  = nodemailer.createTransport({
  host: "smtp-mail.outlook.com", // hostname
  secureConnection: false, // TLS  secureConnection to be false
  port: 587, // port for secure SMTP
  auth: {
      user: "support@identifyyou.in",
      pass: "Idfyu!1234"
  },
  tls: {
      ciphers:'SSLv3'
  }
});
let records_list = [];
exports = {
  onAppInstallHandler: async function () {
    console.log("creatingSchedule... ");
    try {
      await createSchedule();
      console.log("Schedule Created!...");
      await setDB([]);
      console.log("DB Initialized!..");
      renderData(null, true);
    } catch (error) {
      console.log(error);
      renderData(false);
    }
  },
  onAppUninstallHandler: function () {
    console.log("deletingSchedule... ");
    $schedule.delete({name: "one day scheduler_"});
    deleteSchedule().then(
      () => {
        console.log("Schedule Deleted!.");
        renderData(null, true);
      },
      (err) => {
        console.log(err);
        renderData(false);
      }
    );
  },
  onScheduledEventHandler:async function(args) {
    console.log('args.data.name ' , args.data.name);
    if(args.data.name === "minutes"){
      await createRecord(args,args.data.page,args.data.automationId);
    }else if(args.data.name === "days"){
      await create2Schedule();
      console.log("day Schedule triggered!...");
    }else{
      await updateRecord(args,args.data.page,args.data.automationId);
    }
 
}
};

async function createRecord(args,page,id) {
  console.log("page", page,"automationid" ,id);
  try{
    const body= await $request.invokeTemplate("getRules", {
                context: {
                  subdomain: args.iparams.domain,
                  api_key: args.iparams.api_key,
                  page: page,
                  automationid:id
                }
              });
    const response =  JSON.parse(body.response);
    console.log("response.length",response.length);
        if(response.length !== 0){
                  for(let i=0;i<response.length;i++){
                    const obj=  createRecordForEntitty(args,response[i]);
                    const recordData = await  AuomergerPayload.create(obj);
                       console.log(i,recordData);
                  }
             await updateSchedule(args.data.page + 1,args.data.automationId,"minutes");
          }else{
            let automation_type_id = args.data.automationId + 1 ;
                if(automation_type_id === 2){
                  automation_type_id = automation_type_id + 1;
                } 
                console.log('automation_type_id',automation_type_id);
                if(automation_type_id <= 4){
                  await updateSchedule(1,automation_type_id,"minutes");
                }else {
                 
                  await createdaySchedule();
                  deleteSchedule();
                  const storeAutomergerDB =  await $db.update("RulesDB", "set", { rulesIds:[] ,stored:true});
                  console.log("update rule id in DB!.....   -", storeAutomergerDB);
              
                 
                  
              }
          }
}catch(error){
  console.log(error);
  await errorHandling(error,args.iparams);
}
}
function createdaySchedule(){
  const date = new Date();
  // date.setMinutes(date.getMinutes()+6);
  date.setDate(date.getDate() + 1);
  console.log(date);
   return $schedule.create({
              name: "one day scheduler_",
              data: {
                name: "days",
                page: 1,
                automationId:1
              },
              schedule_at: date
            });
   
}
function updateSchedule(page,automation_type_id,name) {
  const date = new Date();
  date.setMinutes(date.getMinutes()+1);
  date.setSeconds(0);
  return $schedule.update({
    name: "one minute scheduler",
    data: {
      name:name,
      page: page,
      automationId:automation_type_id
    },
    schedule_at: date,
    repeat: {
      time_unit: "minutes",
      frequency: 1,
    },
  });
}
function createSchedule() {
  const date = new Date();
  date.setMinutes(date.getMinutes()+1);
  date.setSeconds(0);
  return $schedule.create({
    name: "one minute scheduler",
    data: {
      name:"minutes",
      page: 1,
      automationId:1
    },
    schedule_at: date,
    repeat: {
      time_unit: "minutes",
      frequency: 1,
    },
  });
}

function create2Schedule() {
  const date = new Date();
  date.setMinutes(date.getMinutes()+1);
  date.setSeconds(0);
  return $schedule.create({
    name: "one minute scheduler",
    data: {
      name:"minutes in day",
      page: 1,
      automationId:1
    },
    schedule_at: date,
    repeat: {
      time_unit: "minutes",
      frequency: 1,
    },
  });
}
function deleteSchedule() {
  return $schedule.delete({
    name: "one minute scheduler",
  });
}

function combineConditionsAndActions(data) {
  //   console.log("data",data);
const { performer,events = [],condition_set_1 = [], condition_set_2 = [], operator, actions = [] } = data;
const performerText =  performer ?  performer.replace(/<\/?[^>]+(>|$)/g, "") : "";
//   console.log("performerText",performerText);
const eventsText = events.length ? events.map(stripHTML).join(" "):"";
// Process condition sets
const processedConditionSet1 = condition_set_1.map(stripHTML);
const processedConditionSet2 = condition_set_2.map(stripHTML);

const conditions = [
  ...processedConditionSet1,
  operator ? ` ${operator} ` : "",
  ...processedConditionSet2,
].join(" ");

const actionText = actions.length
  ? actions.map(stripHTML).join(" ")
  : "";

return  {performer:performerText,events:eventsText,conditions:conditions,actions:actionText};
}

// Function to remove HTML tags
function stripHTML(htmlString) {
return htmlString.replace(/<\/?[^>]+(>|$)/g, "");
}


function createRecordForEntitty(args,response){

            const getValues = (data, values= []) => {
              if(typeof data !== 'object'){
                return [...values, data]
              }
              return Object.values(data).flatMap(v => getValues(v, values))
            }
            const actionsarr = getValues(response.actions).join(",");
            // console.log("actionsarr all...>",actionsarr);
            const getCondition = (data, values= []) => {
              if(typeof data !== 'object'){
                return [...values, data]
              }
              return Object.values(data).flatMap(v => getCondition(v, values))
            }
            const conditionsarr = getCondition(response.conditions).join(",");
     
            const summary = response.summary ;
        const combinedContent =  combineConditionsAndActions({
                                         performer:summary.performer,
                                         events:summary.events,
                                         condition_set_1: summary.conditions.condition_set_1,
                                         condition_set_2: summary.conditions.condition_set_2,
                                         operator: summary.conditions.operator,
                                         actions: summary.actions,
                               });
         const data_ =  {
                   summary: `${combinedContent.performer} ${combinedContent.events} ${combinedContent.conditions}${combinedContent.actions}`.trim().toString(), 
                   automation_type_id: args.data.automationId,
                   performer: response.performer? combinedContent.performer.toString():null,
                   active: response.active,
                   created_at: response.created_at.toString(),
                   operator: response.operator? response.operator.toString():null,
                   rule_id: response.id, 
                   affected_tickets_count: response.affected_tickets_count,
                   last_updated_by: response.last_updated_by,
                   outdated: response.outdated, 
                   updated_at: response.updated_at.toString(),
                   name: response.name.toString(),
                   position: response.position, 
                   conditions: conditionsarr.toString(),
                   actions: actionsarr.toString().trim(),
                   events: response.events? combinedContent.events.toString():null 
        };
    return  data_;
}


async function updateRecord(args,page,id) {
  console.log("page", page,"automationid" ,id);
  try{
    const body= await $request.invokeTemplate("getRules", {
                context: {
                  subdomain: args.iparams.domain,
                  api_key: args.iparams.api_key,
                  page: page,
                  automationid:id
                }
              });
    const response =  JSON.parse(body.response);
        const url = {query: { automation_type_id: id }};
          const getrecords_ = await  getrecords(args,url);
          console.log("Total records length...>>  ",getrecords_.length);
          const rulesid = await $db.get("RulesDB");
        if(response.length !== 0){
          for(let m=0;m<response.length;m++){rulesid.rulesIds.push(response[m].id)}
         const storeAutomergerDB =  await $db.update("RulesDB", "set", { rulesIds:rulesid.rulesIds });
          console.log("update rule id in DB!.....   -", storeAutomergerDB);
          const updatecustomobjarr= [] ;
           for(let i=0;i<response.length;i++){
                    const obj=  createRecordForEntitty(args,response[i]);
                       updatecustomobjarr.push(obj);
                  }
                      //  console.log(updatecustomobjarr);
                await updateRecordsByObject(args,updatecustomobjarr,getrecords_);
          
          }else{
                  console.log("rulesid length......>>", rulesid.rulesIds.length);
                     const deleteRecordData = getrecords_.filter((word) => !rulesid.rulesIds.includes(word.data.rule_id));
                   console.log("delted records length....>>> ",deleteRecordData.length);
                for(let a=0;a<deleteRecordData.length;a++){
                  await AuomergerPayload.delete(deleteRecordData[a].display_id);
                  console.log("deleteData",deleteRecordData[a].display_id);
                }
            const storeAutomergerDB =  await $db.update("RulesDB", "set", { rulesIds:[] });
            console.log("update rule id in DB!.....   -", storeAutomergerDB);
            let automation_type_id = args.data.automationId + 1 ;
                if(automation_type_id === 2){
                  automation_type_id = automation_type_id + 1;
                } 
                console.log('changed automation_type_id',automation_type_id);
                if(automation_type_id <= 4){
                  await updateSchedule(1,automation_type_id,"minutes in day");
                }else{
                  await  createdaySchedule();
                  deleteSchedule();
                }
          }
}catch(error){
  // error = {status:403,message:"API key error"}
console.log(error);
await errorHandling(error,args.iparams);
}
}

async function updateRecordsByObject(args,response,getrecords_){
 
  const  updateRecordsData = [];
          for (let i = 0; i < response.length; i++) {
                for (let k = 0; k < getrecords_.length; k++) {
                  if (getrecords_[k].data.rule_id === response[i].rule_id) {
                    // JSON.stringify(getrecords_[k].data),JSON.stringify(response[i])
                      if (JSON.stringify(getrecords_[k].data) !== JSON.stringify(response[i])) {
                          //  console.log("update.records",getrecords_[k].data,response[i]);
                            updateRecordsData.push( {displayid: getrecords_[k].display_id,data:response[i]});
                      }
                  }
                }
              }
     console.log("update customobject record length.....>>>  ",updateRecordsData.length);
     for(let j=0;j<updateRecordsData.length;j++){
          await updateRecordsByObjectinDay(updateRecordsData[j],args);
     }

       const createRecordData = response.filter((elem) => !getrecords_.find(({ data }) => elem.rule_id === data.rule_id));
       console.log("createRecordData..>>> ",createRecordData.length);
       for(let y=0;y<createRecordData.length;y++){
        createRecordsByObject(args,createRecordData[y]);
        } 
        
         await updateSchedule(args.data.page + 1,args.data.automationId,"minutes in day");
  
}

function  getrecords(args,url){
  return new Promise(async function (resolve, reject) {
  try{
    const Auomergerdb = await AuomergerPayload.getAll(url);
    // console.log("Auomergerdb!...",Auomergerdb.records.length);
         if (Auomergerdb.records && Auomergerdb.records.length !== 0){
            records_list = records_list.concat(Auomergerdb.records);  
            if(Auomergerdb.links && Auomergerdb.links.next){
              url["next"] = Auomergerdb.links.next;
              // console.log("record._links.next",url);
              await getrecords(args,url);
            }
        }
        resolve(records_list);
    }catch(error){
      await errorHandling(error,args.iparams);
      reject(error);
      }
    });
}


async function   updateRecordsByObjectinDay(updateRecordsData,args){
  try{
    const newData = {
      ...updateRecordsData.data
    };
     console.log("displayid",updateRecordsData.displayid);
      const updateData = await AuomergerPayload.update(updateRecordsData.displayid,newData);      
     console.log("updateData",updateData);
  }catch(error){         
    console.log("updateData error",error);
      await errorHandling(error,args.iparams);
 }
  
}

async function    createRecordsByObject(args,createRecordData){
  try{
    const recordData = await  AuomergerPayload.create(createRecordData);
    console.log(recordData);
  }catch(error){         
    console.log("error",error);
      await errorHandling(error,args.iparams);
 }
}
// async function deleteRecordsincustomobject(args,deleteRecordData){
//   try{
//     const deleteData =  await AuomergerPayload.delete(deleteRecordData.display_id);
//                 console.log(deleteData);
//   }catch(error){         
//     console.log("error",error);
//       await errorHandling(error,args.iparams);
//  }
// }

function setDB(dRules) {
  return new Promise((resolve, reject) => {
    $db.set("RulesDB", {rulesIds:dRules,stored:false}).then(
      () => {
        console.log("setting ticket ids...", dRules);
        resolve(dRules);
      },
      (err) => {
        reject(err);
      } 
    );
  });
}

async function errorHandling(error,iparams) {
  if (error.status === 429) {
          try{
            await $db.get('sendOneMail');
               await  $db.update('sendOneMail', "increment", {"Interactions": 1});
          }catch(error){
                  console.log('else part');
                  await $db.set( 'sendOneMail', { "statusCode": 429 }, {ttl: 300});
                 await  $db.update('sendOneMail', "increment", {"Interactions": 1});
                 let email_already = await $db.get('sendOneMail');
                 if(email_already.Interactions === 1){
                  await sendEmail("warning",error,iparams);
                 }
                }
    
  }else if (error.status === 401 || error.status === 403 || error.status === 500){
       await sendEmail("erroring",error,iparams);
  }

}


async function sendEmail(data,error,iparams) {

let  emailSubject;
let emailBody;
let toemail_ids = [] ;

for (let i = 0; i < iparams.agentEmail.length; i++) {
toemail_ids.push(iparams.agentEmail[i]);
}
if(iparams.toemail.length !== ""){
const emails = iparams.toemail.split(',');
for (let j = 0; j < emails.length; j++) {
  toemail_ids.push(emails[j]);
}
}
toemail_ids = toemail_ids.filter( function( item, index, inputArray ) {
  return inputArray.indexOf(item) === index;
});
let msg;
if(error.response){
msg = JSON.parse(error.response).message;
}else{
// console.log(error);
msg = error.message;
}
if(data === "warning"){
 emailSubject = "Warning: Workfolw Automation Tool App API rate limit warning.";
  emailBody  ="Dear User,<br><br>Hope this email finds you well.<br><br>The application has identified that your API usage has either reached or exceeded the allocated rate limit for your account. As a result, the merge functionality will be temporarily disabled for one minute. However, during this time, the application will continue to capture any newly created ticket IDs. Once the minute has elapsed, the application will automatically retry the merge process with the accumulated ticket IDs.<br><br>If you have any questions or concerns, please do not hesitate to contact our support team at [<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>].<br><br>Thank you for your attention to this matter.<br><br>Best regards,<br>Support,<br>IdentifYou."
}
else{
    emailSubject = "Urgent:  Workfolw Automation Tool App Error Notification.";
   emailBody  =`Dear User,<br><br>Hope this email finds you well.<br><br>We regret to inform you that our application has encountered an error and is currently non-functional. The issue may be attributed to the following error:<br><br><b>${msg}</b><br><br>We kindly request you to investigate the application and take necessary actions to resolve the issue. We apologize for any inconvenience this may cause and sincerely appreciate your patience and understanding.<br><br>If you have any questions or concerns, please do not hesitate to contact our support team at [<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>].<br><br>Thank you for your attention to this matter.<br><br>Best regards,<br>Support,<br>IdentifYou.`  
    }
    const emaildata = {
  from: "support@identifyyou.in",
  to: toemail_ids,
  subject: emailSubject,
  html: `${emailBody}`
};
console.log("emaildata: ", emaildata);
              // send mail with defined transport object
              const info = await transporter.sendMail(emaildata);
              console.log("Message sent:", info.messageId);
        
}




EXPLAIN THIS