/home/edulekha/crm.edulekha.com/modules/appointly/assets/js/outlook_js.php
<script type="text/javascript" src="https://alcdn.msauth.net/lib/1.3.4/js/msal.js"></script>
<script>
     var outlookConf = {
          msalConfig: {
               auth: {
                    clientId: "<?= get_option('appointly_outlook_client_id') ?>",
                    authority: "https://login.microsoftonline.com/common",
                    redirectUri: admin_url + 'appointly/appointments',
               },
               cache: {
                    cacheLocation: "localStorage",
                    storeAuthStateInCookie: true
               },
               system: {
                    loadFrameTimeout: 50000
               }
          },
          graphConfig: {
               graphMeEndpoint: "https://graph.microsoft.com/v1.0/me"
          },
          requestObj: {
               scopes: ["openid", "User.ReadWrite", "Calendars.ReadWrite"]
          }
     }
     var myMSALObj = new Msal.UserAgentApplication(outlookConf.msalConfig);
     // Register Callbacks for redirect flow
     myMSALObj.handleRedirectCallback(authRedirectCallBack);

     function signInToOutlook(event) {
          // Prevent default action if called from a link
          if (event && event.preventDefault) {
               event.preventDefault();
          }

          console.log('Signing in to Outlook...');

          myMSALObj.loginPopup(outlookConf.requestObj).then(function(loginResponse) {
               if (loginResponse.fromCache === false) {
                    window.location.reload();
               }
               //Successful login
               checkOutlookAuthentication();
               //Call MS Graph using the token in the response
               // acquireTokenPopupAndCallMSGraph();
          }).catch(function(error) {
               renderErrorToConsole(error);
          });
     }

     function outlookSignOut(event) {
          // Prevent default action if called from a link
          if (event && event.preventDefault) {
               event.preventDefault();
          }

          console.log('Signing out from Outlook...');

          // First, clear MSAL cache
          myMSALObj.clearCache();

          // Properly logout from MSAL
          myMSALObj.logout({
               onRedirectNavigate: (url) => {
                    // Return false to stop navigation after local logout
                    return false;
               }
          });

          // Clear localStorage
          Object.keys(localStorage).forEach(key => {
               if (key.startsWith('msal.') || key.includes('outlook')) {
                    localStorage.removeItem(key);
               }
          });

          // Clear session storage
          Object.keys(sessionStorage).forEach(key => {
               if (key.startsWith('msal.') || key.includes('outlook')) {
                    sessionStorage.removeItem(key);
               }
          });

          // Clear cookies
          var msalCookies = document.cookie.split(/=[^;]*(?:;\s*|$)/);
          for (var i = 0; i < msalCookies.length; i++) {
               if (/^msal/.test(msalCookies[i])) {
                    document.cookie = msalCookies[i] + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
               }
          }

          // Update UI
          var loginButton = document.getElementById('sign_in_outlook');
          if (loginButton) {
               loginButton.innerHTML = '<i class="fa-regular fa-envelope" aria-hidden="true"><?= _l('appointment_connect') ?>';
               loginButton.title = "<?= _l('appointment_connect') ?>";
               loginButton.removeEventListener('click', outlookSignOut);
               loginButton.addEventListener('click', signInToOutlook);
          }

          // Reload page to reset state
          window.location.reload();
     }

     function acquireTokenPopupAndCallMSGraph() {
          //Always start with acquireTokenSilent to obtain a token in the signed in user from cache
          myMSALObj.acquireTokenSilent(outlookConf.requestObj).then(function(tokenResponse) {
               callMSGraph(outlookConf.graphConfig.graphMeEndpoint, tokenResponse.accessToken);
               // getOutlookEvents("https://graph.microsoft.com/v1.0/me/calendar/events", tokenResponse.accessToken);
          }).catch(function(error) {
               renderErrorToConsole(error);
               // Upon acquireTokenSilent failure (due to consent or interaction or login required ONLY)
               // Call acquireTokenPopup(popup window)
               if (requiresInteraction(error.errorCode)) {
                    document.getElementById('sign_in_outlook').innerHTML = "<?= _l('appointment_login_to_outlook') ?>";
                    myMSALObj.acquireTokenPopup(outlookConf.requestObj).then(function(tokenResponse) {
                         callMSGraph(outlookConf.graphConfig.graphMeEndpoint, tokenResponse.accessToken);
                         // getOutlookEvents("https://graph.microsoft.com/v1.0/me/calendar/events", tokenResponse.accessToken);
                    }).catch(function(error) {
                         renderErrorToConsole(error);
                    });
               }
          });
     }

     function callMSGraph(url, accessToken) {
          var msAccessToken = document.getElementById('ms-access-token');
          if (msAccessToken !== null) {
               msAccessToken.value = accessToken;
          } else {
               console.log('ms-access-token element not found, but proceeding with API call');
          }

          var xmlHttp = new XMLHttpRequest();
          /**
           * True for asynchronous
           */
          xmlHttp.open("GET", url, true);
          xmlHttp.setRequestHeader('Authorization', 'bearer ' + accessToken);
          xmlHttp.send();
     }

     function checkOutlookAuthentication() {
          var loginButton = document.getElementById('sign_in_outlook');

          // If the button doesn't exist, just return without trying to modify it
          if (!loginButton) {
               console.log('Outlook login button not found on this page');
               return;
          }

          // Check if the user is authenticated with Outlook
          if (myMSALObj.getAccount()) {
               loginButton.innerHTML = '<i class="fa-solid fa-check-circle tw-text-success-600 tw-mr-1"></i> <?= _l('appointment_connected'); ?>';
               loginButton.classList.remove('tw-text-primary-600');
               loginButton.classList.add('tw-text-success-600');
               loginButton.title = "<?= _l('appointments_outlook_revoke') ?>";

               // Remove any existing event listeners by cloning and replacing
               var newLoginButton = loginButton.cloneNode(true);
               loginButton.parentNode.replaceChild(newLoginButton, loginButton);
               loginButton = newLoginButton;

               // Create a new function for handling click with confirmation
               loginButton.addEventListener('click', function(e) {
                    e.preventDefault();
                    if (confirm("<?= _l('appointments_outlook_revoke_confirm') ?>")) {
                         outlookSignOut(e);
                    }
               });
          } else {
               loginButton.innerHTML = '<?= _l('appointment_connect'); ?> <i class="fa fa-arrow-right tw-ml-1"></i>';
               loginButton.classList.remove('tw-text-success-600');
               loginButton.classList.add('tw-text-primary-600');
               loginButton.title = "<?= _l('appointment_connect') ?>";

               // Remove any existing event listeners by cloning and replacing
               var newLoginButton = loginButton.cloneNode(true);
               loginButton.parentNode.replaceChild(newLoginButton, loginButton);
               loginButton = newLoginButton;

               // Add click event for sign in
               loginButton.addEventListener('click', function(e) {
                    e.preventDefault();
                    signInToOutlook();
               });
          }
     }

     function authRedirectCallBack(error, response) {
          if (error) {
               console.error('Outlook auth redirect error:', error);
               renderErrorToConsole(error);
          } else {
               if (response && response.tokenType === "access_token") {
                    console.log('Got access token from redirect');

                    // Make sure we're being safe about updating DOM elements
                    var msAccessToken = document.getElementById('ms-access-token');
                    if (msAccessToken) {
                         msAccessToken.value = response.accessToken;
                    }

                    callMSGraph(outlookConf.graphConfig.graphMeEndpoint, response.accessToken);
               }
          }
     }

     function requiresInteraction(errorCode) {
          if (!errorCode || !errorCode.length) {
               return false;
          }
          return errorCode === "consent_required" ||
               errorCode === "interaction_required" ||
               errorCode === "login_required";
     }

     async function outlookAddOrUpdateEvent(data) {
          if (!isOutlookLoggedIn()) {
               return false;
          }

          var accessToken = document.getElementById('ms-access-token').value;
          var eventId = document.getElementById('ms-outlook-event-id').value;

          var paramData = [];
          var outlook_attendees = [];
          var normal_date = '';
          var event = '';
          var attendees_data = '';

          data.map(function(form) {
               if (form['name'] == 'attendees[]') {
                    outlook_attendees.push(form['value'])
               }
               paramData[form['name']] = form['value'];
          });

          paramData.attendees = [outlook_attendees];

          delete paramData['attendees[]'];

          var attendeeDataPromisse = new Promise(function(resolve, reject) {
               return resolve($.post(site_url + 'appointly/appointments/getAttendeeData', {
                    ids: Object.values(outlook_attendees)
               }));
          })

          attendeeDataPromisse.then(function(attendees) {
               // selected contact to attendee list
               if ($('body').find('#div_email input').val().length > 0) {
                    var clientContactLead = {
                         emailAddress: {
                              address: $('body').find('#div_email input').val(),
                              name: $('body').find('#div_name input').val(),
                         }
                    }
                    attendees.push(clientContactLead);
               }
               return attendees;
          });

          var attendees_data = await attendeeDataPromisse;

          paramData.date = moment(paramData.date, ['DD/MM/YYYY HH:mm:ss', 'DD.MM.YYYY HH:mm:ss', 'MM-DD-YYYY HH:mm:ss', 'MM.DD.YYYY HH:mm:ss', 'MM/DD/YYYY HH:mm:ss', 'YYYY-MM-DD HH:mm:ss']).format();

          event = {
               subject: paramData.subject,
               body: {
                    contentType: "HTML",
                    content: paramData.description
               },
               start: {
                    dateTime: paramData.date,
                    timeZone: app.options.timezone
               },
               end: {
                    dateTime: paramData.date,
                    timeZone: app.options.timezone
               },
               location: {
                    displayName: (paramData.address) ? paramData.address : ''
               },
               attendees: attendees_data,
               Importance: "Normal",
               HasAttachments: false,
               isReminderOn: true,
               reminderMinutesBeforeStart: <?= get_option('appointly_google_meet_reminder_minutes') ?: 30 ?>
          };

          var url = 'https://graph.microsoft.com/v1.0/me/events/';
          var requestType = 'POST';

          // used for updating event
          if (typeof eventId != 'undefined' && eventId != '') {
               requestType = 'PATCH'
               url += eventId;
          }

          var dfd = jQuery.Deferred();
          var promise = dfd.promise();

          $.ajax({
               url,
               type: requestType,
               headers: {
                    'Content-Type': 'application/json;charset=UTF-8',
                    'Authorization': 'Bearer ' + accessToken,
               },
               data: JSON.stringify(event)
          }).done(function(appointment) {
               if (appointment.id) {
                    $.post(site_url + 'appointly/appointments/newOutlookEvent', {
                         outlook_event_id: appointment.id,
                         outlook_calendar_link: appointment.webLink,
                    }).done(function(r) {
                         dfd.resolve();
                         if (r.result) {
                              if (requestType == 'POST') {
                                   alert_float('success', "<?= _l('appointment_created') ?>");
                              } else {
                                   alert_float('success', "<?= _l('appointment_updated') ?>");
                              }

                              // Instead of reloading the page, refresh the table and close the modal
                              if ($.fn.DataTable.isDataTable('.table-appointments')) {
                                   $('.table-appointments').DataTable().ajax.reload(null, false);
                              }
                              $('.modal').modal('hide');
                         }
                    });
               }
          }).fail(function(error) {
               renderErrorToConsole(error);
          });
          promise.then(function() {
               return dfd.promise();
          })
     }

     function addToOutlookNewEventFromUpdate(data) {
          // Get the appointment ID from the form or parameter
          var appointment_id;

          // Handle both when data is the ID directly (from button click)
          // or when it's form data (from form submission)
          if (typeof data === 'number' || typeof data === 'string') {
               appointment_id = data;
          } else {
               appointment_id = $('input[name="appointment_id"]').val();
          }

          if (!isOutlookLoggedIn()) {
               signInToOutlook();
               return false;
          }

          // Get fresh token
          myMSALObj.acquireTokenSilent(outlookConf.requestObj)
               .then(function(tokenResponse) {
                    var accessToken = tokenResponse.accessToken;
                    var outlook_attendees = [];
                    if (Array.isArray(data)) {
                         data.forEach(function(form) {
                              if (form['name'] == 'attendees[]') {
                                   outlook_attendees.push(form['value']);
                              }
                         });
                    } else {
                         // For update.php (direct form selector)
                         var attendeesSelect = $('select[name="attendees[]"]');
                         if (attendeesSelect.length) {
                              outlook_attendees = attendeesSelect.val() || [];
                         }
                    }

                    // Get attendee data if we have staff IDs to fetch
                    if (outlook_attendees.length > 0) {
                         $.post(site_url + 'appointly/appointments/getAttendeeData', {
                              ids: outlook_attendees,
                              <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                         }).done(function(attendees) {
                              console.log('Raw attendees response:', attendees);
                              console.log('Type of attendees:', typeof attendees);

                              try {
                                   if (typeof attendees === 'string') {
                                        attendees = JSON.parse(attendees);
                                   }
                              } catch (e) {
                                   console.log('JSON parse error:', e);
                                   attendees = [];
                              }

                              console.log('Parsed attendees:', attendees);
                              console.log('Is array?', Array.isArray(attendees));

                              // Ensure attendees is always an array
                              if (!Array.isArray(attendees)) {
                                   console.log('Converting to array, current type:', typeof attendees);
                                   attendees = [];
                              }

                              // Add the provider (service provider) to attendees
                              var provider_id = $('select[name="provider_id"]').val();
                              console.log('Provider ID:', provider_id);

                              if (provider_id) {
                                   // Get provider details via AJAX
                                   $.post(site_url + 'appointly/appointments/getAttendeeData', {
                                        ids: [provider_id],
                                        <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                                   }).done(function(providerData) {
                                        console.log('Provider data received:', providerData);
                                        try {
                                             if (typeof providerData === 'string') {
                                                  providerData = JSON.parse(providerData);
                                             }
                                             if (Array.isArray(providerData) && providerData.length > 0) {
                                                  attendees = attendees.concat(providerData);
                                             }
                                        } catch (e) {
                                             console.log('Error parsing provider data:', e);
                                        }

                                        // Add related contact based on appointment type
                                        addRelatedContactAndCreateEvent(attendees);
                                   }).fail(function() {
                                        console.log('Failed to get provider data');
                                        // Still try to add related contact
                                        addRelatedContactAndCreateEvent(attendees);
                                   });
                              } else {
                                   // No provider, just add related contact
                                   addRelatedContactAndCreateEvent(attendees);
                              }

                              function addRelatedContactAndCreateEvent(attendees) {
                                   // Add external contact if appointment is external
                                   var rel_type = $('select[name="rel_type"]').val();
                                   console.log('Appointment type:', rel_type);

                                   if (rel_type === 'external') {
                                        var external_name = $('input[name="name"]').val();
                                        var external_email = $('input[name="email"]').val();
                                        console.log('External contact:', external_name, external_email);

                                        if (external_name && external_email) {
                                             attendees.push({
                                                  emailAddress: {
                                                       address: external_email,
                                                       name: external_name
                                                  },
                                                  type: "required"
                                             });
                                        }
                                   } else if (rel_type === 'internal') {
                                        // For internal appointments, check if there's a selected contact
                                        var contact_select = $('select[name="contact_id"]');
                                        var contact_id = contact_select.val();

                                        if (contact_id) {
                                             var selectedOption = contact_select.find('option:selected');
                                             var contactText = selectedOption.text();

                                             // Fetch contact email via AJAX
                                             $.post(site_url + 'appointly/appointments/getContactEmail', {
                                                  contact_id: contact_id,
                                                  <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                                             }).done(function(contactEmailData) {
                                                  if (typeof contactEmailData === 'string') {
                                                       contactEmailData = JSON.parse(contactEmailData);
                                                  }

                                                  if (contactEmailData && contactEmailData.email) {
                                                       attendees.push({
                                                            emailAddress: {
                                                                 address: contactEmailData.email,
                                                                 name: contactEmailData.name || contactText.split(' - ')[0]
                                                            },
                                                            type: "required"
                                                       });
                                                  }

                                                  // Continue with event creation after trying to add contact
                                                  console.log('Final attendees array before creating event:', attendees);
                                                  createOutlookEvent(attendees);
                                             }).fail(function(xhr, status, error) {
                                                  console.log('Failed to get contact email:', status, error);

                                                  // Continue without contact email
                                                  console.log('Final attendees array before creating event:', attendees);
                                                  createOutlookEvent(attendees);
                                             });

                                             return; // Exit here, createOutlookEvent will be called from AJAX callback
                                        }
                                   }

                                   console.log('Final attendees array before creating event:', attendees);
                                   createOutlookEvent(attendees);
                              }
                         }).fail(function(xhr, status, error) {
                              console.log('Failed to get attendee data:', status, error);
                              console.log('XHR response:', xhr.responseText);
                              createOutlookEvent([]);
                         });
                    } else {
                         console.log('No staff attendees selected, but will add provider and related contact');

                         // Start with empty array
                         var attendees = [];

                         // 1. Add the provider (service provider) to attendees
                         var provider_id = $('select[name="provider_id"]').val();
                         console.log('Provider ID:', provider_id);

                         if (provider_id) {
                              // Get provider details via AJAX
                              $.post(site_url + 'appointly/appointments/getAttendeeData', {
                                   ids: [provider_id],
                                   <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                              }).done(function(providerData) {
                                   console.log('Provider data received:', providerData);
                                   try {
                                        if (typeof providerData === 'string') {
                                             providerData = JSON.parse(providerData);
                                        }
                                        if (Array.isArray(providerData) && providerData.length > 0) {
                                             attendees = attendees.concat(providerData);
                                        }
                                   } catch (e) {
                                        console.log('Error parsing provider data:', e);
                                   }

                                   // 2. Add related contact based on appointment type
                                   addRelatedContactAndCreateEvent(attendees);
                              }).fail(function() {
                                   console.log('Failed to get provider data');
                                   // Still try to add related contact
                                   addRelatedContactAndCreateEvent(attendees);
                              });
                         } else {
                              // No provider, just add related contact
                              addRelatedContactAndCreateEvent(attendees);
                         }

                         function addRelatedContactAndCreateEvent(attendees) {
                              var rel_type = $('select[name="rel_type"]').val();

                              if (rel_type === 'external') {
                                   var external_name = $('input[name="name"]').val();
                                   var external_email = $('input[name="email"]').val();

                                   if (external_name && external_email) {
                                        attendees.push({
                                             emailAddress: {
                                                  address: external_email,
                                                  name: external_name
                                             },
                                             type: "required"
                                        });
                                   }
                              } else if (rel_type === 'lead_related') {
                                   var contact_select = $('select[name="contact_id"]');
                                   var contact_id = contact_select.val();

                                   if (contact_id) {
                                        var selectedOption = contact_select.find('option:selected');
                                        var contactText = selectedOption.text();
                                   }
                              } else if (rel_type === 'internal') {

                                   // For internal appointments, check if there's a selected contact
                                   var contact_select = $('select[name="contact_id"]');
                                   var contact_id = contact_select.val();

                                   if (contact_id) {
                                        var selectedOption = contact_select.find('option:selected');
                                        var contactText = selectedOption.text();

                                        // Fetch contact email via AJAX
                                        $.post(site_url + 'appointly/appointments/getContactEmail', {
                                             contact_id: contact_id,
                                             <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                                        }).done(function(contactEmailData) {
                                             if (typeof contactEmailData === 'string') {
                                                  contactEmailData = JSON.parse(contactEmailData);
                                             }

                                             if (contactEmailData && contactEmailData.email) {
                                                  attendees.push({
                                                       emailAddress: {
                                                            address: contactEmailData.email,
                                                            name: contactEmailData.name || contactText.split(' - ')[0]
                                                       },
                                                       type: "required"
                                                  });
                                             }

                                             // Continue with event creation after trying to add contact
                                             createOutlookEvent(attendees);
                                        }).fail(function(xhr, status, error) {
                                             console.log('Failed to get contact email:', status, error);

                                             // Continue without contact email
                                             createOutlookEvent(attendees);
                                        });

                                        return; // Exit here, createOutlookEvent will be called from AJAX callback
                                   }
                              }

                              createOutlookEvent(attendees);
                         }
                    }

                    function createOutlookEvent(attendees) {
                         // Get date based on form type
                         var date;

                         if (Array.isArray(data)) {
                              date = data.find(item => item.name === 'date')?.value;
                         } else {
                              date = $('input[name="date"]').val();
                         }

                         var formattedDate = moment(date, [
                              'DD/MM/YYYY HH:mm',
                              'DD.MM.YYYY HH:mm',
                              'MM-DD-YYYY HH:mm',
                              'MM.DD.YYYY HH:mm',
                              'MM/DD/YYYY HH:mm',
                              'YYYY-MM-DD HH:mm'
                         ]).format();

                         // Create event object
                         var event = {
                              subject: Array.isArray(data) ?
                                   (data.find(item => item.name === 'subject')?.value || '') : $('input[name="subject"]').val(),
                              body: {
                                   contentType: "HTML",
                                   content: Array.isArray(data) ?
                                        (data.find(item => item.name === 'description')?.value || '') : $('textarea[name="description"]').val()
                              },
                              start: {
                                   dateTime: formattedDate,
                                   timeZone: app.options.timezone
                              },
                              end: {
                                   dateTime: moment(formattedDate).add(1, 'hour').format(),
                                   timeZone: app.options.timezone
                              },
                              location: {
                                   displayName: Array.isArray(data) ?
                                        (data.find(item => item.name === 'address')?.value || '') : $('input[name="address"]').val()
                              },
                              attendees: attendees,
                              isReminderOn: true,
                              reminderMinutesBeforeStart: <?= get_option('appointly_google_meet_reminder_minutes') ?: 30 ?>
                         };

                         // Create event in Outlook
                         $.ajax({
                              url: 'https://graph.microsoft.com/v1.0/me/events',
                              type: 'POST',
                              headers: {
                                   'Content-Type': 'application/json',
                                   'Authorization': 'Bearer ' + accessToken,
                              },
                              data: JSON.stringify(event),
                              beforeSend: function() {
                                   $('#addToOutlookBtn').prop('disabled', true)
                                        .html('<i class="fa fa-refresh fa-spin fa-fw"></i> <?= _l("appointment_calendar_adding_to_outlook") ?>');
                              }
                         }).done(function(response) {
                              if (response.id) {
                                   $.post(site_url + 'appointly/appointments/save_outlook_event_id', {
                                        appointment_id: appointment_id,
                                        outlook_event_id: response.id,
                                        outlook_calendar_link: response.webLink || '',
                                        <?= $this->security->get_csrf_token_name() ?>: '<?= $this->security->get_csrf_hash() ?>'
                                   }).done(function(response) {
                                        alert_float('success', "<?= _l('appointment_added_to_outlook') ?>");
                                        window.location.reload();
                                        $('.modal').modal('hide');

                                   }).fail(function(xhr, status, error) {
                                        alert_float('danger', "<?= _l('appointment_outlook_event_save_failed') ?>");
                                        $('#addToOutlookBtn').prop('disabled', false)
                                             .html("<?= _l('appointment_add_to_outlook') ?> <i class=\"fa fa-envelope\"></i>");
                                   });
                              }
                         }).fail(function(xhr) {
                              if (xhr.status === 401) {
                                   myMSALObj.acquireTokenPopup(outlookConf.requestObj)
                                        .then(function(newTokenResponse) {
                                             accessToken = newTokenResponse.accessToken;
                                             addToOutlookNewEventFromUpdate(data);
                                        })
                                        .catch(function(error) {
                                             alert_float('danger', "<?= _l('appointment_outlook_auth_error') ?>");
                                        });
                              } else {
                                   alert_float('danger', "<?= _l('appointment_outlook_error') ?>");
                              }
                              $('#addToOutlookBtn').prop('disabled', false)
                                   .html("<?= _l('appointment_add_to_outlook') ?> <i class=\"fa fa-envelope\"></i>");
                         });
                    }
               })
               .catch(function(error) {
                    if (requiresInteraction(error.errorCode)) {
                         myMSALObj.acquireTokenPopup(outlookConf.requestObj)
                              .then(function(tokenResponse) {
                                   addToOutlookNewEventFromUpdate(data);
                              })
                              .catch(function(error) {
                                   alert_float('danger', "<?= _l('appointment_outlook_auth_error') ?>");
                              });
                    }
               });
     }

     function deleteOutlookEvent(id, showAlert = true) {
          if (!id) {
               return false;
          }

          if (isOutlookLoggedIn()) {
               myMSALObj.acquireTokenSilent(outlookConf.requestObj).then(function(Response) {
                    if (Response.accessToken) {
                         $.ajax({
                                   url: 'https://graph.microsoft.com/v1.0/me/events/' + id,
                                   type: 'DELETE',
                                   beforeSend: function(xhr) {
                                        xhr.setRequestHeader('Authorization', 'Bearer ' + Response.accessToken);
                                   }
                              }).done(function() {
                                   if (showAlert) {
                                        alert_float('success', "<?= _l('appointment_outlook_event_deleted') ?>");
                                   }
                              })
                              .fail(function(error) {
                                   renderErrorToConsole(error);
                                   if (showAlert) {
                                        alert_float('danger', "<?= _l('appointment_outlook_event_delete_failed') ?>");
                                   }
                              });
                    } else {
                         return false;
                    }
               }).catch(function(error) {
                    renderErrorToConsole(error);
                    return false;
               });
          } else {
               return false;
          }
     }

     /**
      * Fetch outlook events
      */
     function getOutlookEvents(url, token) {
          $.ajax({
                    url,
                    type: 'GET',
                    beforeSend: function(xhr) {
                         xhr.setRequestHeader('Authorization', 'Bearer ' + token);
                    },
                    data: {}
               }).done(function() {
                    // done
               })
               .fail(function(error) {
                    renderErrorToConsole(error);
               });
     }

     /**
      * Error Log renderer
      */
     function renderErrorToConsole(error) {
          console.log(error)
     }

     // Browser check variables
     var ua = window.navigator.userAgent;
     var msie = ua.indexOf('MSIE ');
     var msie11 = ua.indexOf('Trident/');
     var msedge = ua.indexOf('Edge/');
     var isIE = msie > 0 || msie11 > 0;
     var isEdge = msedge > 0;

     //If you support IE, our recommendation is that you sign-in using Redirect APIs
     //If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check

     // can change this to default an experience outside browser use
     var loginType = isIE ? "REDIRECT" : "POPUP";

     // Initialize button handlers when the document is ready
     document.addEventListener('DOMContentLoaded', function() {
          // Find the sign in button
          var signInButton = document.getElementById('sign_in_outlook');

          // Only set up event handlers if the button exists
          if (signInButton) {
               // Call the authentication check which will set up the event handlers
               checkOutlookAuthentication();
          }
     });

     // runs on page load, change config to try different login types to see what is best for your application
     if (loginType === 'POPUP') {
          // Initialization is now handled by the DOMContentLoaded event listener above
     } else if (loginType === 'REDIRECT') {
          // avoid duplicate code execution on page load in case of iframe and popup window.
          if (myMSALObj.getAccount() && !myMSALObj.isCallback(window.location.hash)) {
               // The UI will be updated by the DOMContentLoaded event listener
          }
     } else {
          console.error('Please set a valid login type');
     }

     /**
      * Check if user is logged in to Outlook
      * @return {boolean} True if logged in, false otherwise
      */
     function isOutlookLoggedIn() {
          // Check if the user has an account in MSAL
          if (typeof myMSALObj !== "undefined" && myMSALObj.getAccount()) {
               return true;
          }

          // Check if we have an access token in the DOM
          var msAccessToken = document.getElementById('ms-access-token');
          if (msAccessToken && msAccessToken.value) {
               return true;
          }

          return false;
     }
</script>