namespace Hims.Infrastructure.Helpers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    using Domain.Configurations;
    using Domain.Entities;
    using Domain.Helpers;
    using Domain.Repositories.UnitOfWork;

    using Models;

    using Newtonsoft.Json;

    using RestSharp;

    using Shared.EntityModels;
    using Shared.Library.Enums;
    using Shared.UserModels;

    /// <inheritdoc />
    public class PushNotificationHelper : IPushNotificationHelper
    {
        /// <summary>
        /// The FCM configuration.
        /// </summary>
        private readonly IFCMConfiguration fcmConfiguration;

        /// <summary>
        /// The client.
        /// </summary>
        private RestClient client;

        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;
        /// <summary>
        /// The AES helper.
        /// </summary>
        private readonly IAESHelper aesHelper;

        /// <summary>
        /// Initializes a new instance of the <see cref="PushNotificationHelper"/> class.
        /// </summary>
        /// <param name="fcmConfiguration">
        /// The fcm configuration.
        /// </param>
        /// <param name="unitOfWork"></param>
        public PushNotificationHelper(
            IFCMConfiguration fcmConfiguration,
            IUnitOfWork unitOfWork,
              IAESHelper aesHelper
        )
        {
            this.fcmConfiguration = fcmConfiguration;
            this.unitOfWork = unitOfWork;
            this.aesHelper = aesHelper;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> deviceTokensForAndroid,
            IEnumerable<string> deviceTokensForIOS,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationRequestModel requestBody;

            IRestResponse response = null;

            var tokensForAndroid = deviceTokensForAndroid as string[] ?? deviceTokensForAndroid.ToArray();
            if (tokensForAndroid.Any())
            {
                var data = new Data
                {
                    Message = body,
                    Type = message
                };
                var registrationIds = tokensForAndroid.Select(m => m)
                    .ToArray();
                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationIds,
                    Data = data
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.Android, type);
            }

            var tokensForIOS = deviceTokensForIOS as string[] ?? deviceTokensForIOS.ToArray();
            if (tokensForIOS.Any())
            {
                var data = new Data
                {
                    Message = message,
                    Type = body
                };
                var registrationIds = tokensForIOS.Select(m => m)
                    .ToArray();
                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationIds,
                    Data = data,
                    Notification = new Notification { Title = title, Body = body }
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.IOS, type);
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendAltAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> deviceTokensForAndroid,
            IEnumerable<string> deviceTokensForIOS,
            string doctorName,
            string date,
            string prevDate = null,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationRequestModel requestBody;

            IRestResponse response = null;

            var tokensForAndroid = deviceTokensForAndroid as string[] ?? deviceTokensForAndroid.ToArray();
            if (tokensForAndroid.Any())
            {
                var data = new Data
                {
                    Message = body,
                    Type = message,
                    DoctorName = doctorName,
                    Date = date,
                    PreviousDate = prevDate
                };

                var registrationIds = tokensForAndroid.Select(m => m).ToArray();

                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationIds,
                    Data = data
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.Android, type);
            }

            var tokensForIOS = deviceTokensForIOS as string[] ?? deviceTokensForIOS.ToArray();
            if (tokensForIOS.Any())
            {
                var data = new Data
                {
                    Message = message,
                    Type = body,
                    DoctorName = doctorName,
                    Date = date
                };

                var registrationIds = tokensForIOS.Select(m => m).ToArray();

                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationIds,
                    Data = data,
                    Notification = new Notification { Title = title, Body = body }
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.IOS, type);
            }

            return response;
        }

        /// <summary>
        /// The log async.
        /// </summary>
        /// <param name="data">
        /// The data.
        /// </param>
        /// <param name="tokens">
        /// The tokens.
        /// </param>
        /// <param name="response">
        /// The response.
        /// </param>
        /// <param name="to">
        /// The to.
        /// </param>
        /// <typeparam name="T">
        /// T is data
        /// </typeparam>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task LogAsync<T>(T data, IEnumerable<string> tokens, IRestResponse response, ToType to, NotificationType? type, int? accountId = null)
        {
            try
            {
                await this.unitOfWork.NotificationLog.InsertAsync(new NotificationLog
                {
                    AccountId = accountId,
                    Data = JsonConvert.SerializeObject(data),
                    DeviceIds = string.Join(",", tokens),
                    Response = JsonConvert.SerializeObject(response.Content),
                    Status = response.IsSuccessful ? "Success" : "Failure",
                    ToTypeId = to,
                    NotificationTypeId = type
                });
            }
            catch (Exception)
            {
                // ignore
            }
        }

        /// <inheritdoc />
        public async Task<IRestResponse> IntimateAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> deviceTokensForAndroid,
            IEnumerable<string> deviceTokensForIOS,
            string id,
            NotificationType? type = null)
        {
            //var appId = this.aesHelper.Decrypt(id);

            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationIntimateModel requestBody;

            IRestResponse response = null;

            var tokensForIOS = deviceTokensForIOS as string[] ?? deviceTokensForIOS.ToArray();
            if (tokensForIOS.Any())
            {
                var registrationIds = tokensForIOS.Select(m => m).ToArray();

                foreach (var deviceId in registrationIds)
                {
                    if (deviceId.ToUpper() == "string".ToUpper() || deviceId == "" || deviceId == null)
                    {
                        continue;
                    }

                    var deviceIdArray = new[] { deviceId };
                    var data = new IntimateData
                    {
                        Message = message,
                        Type = body,
                        Id = id
                    };
                    requestBody = new PushNotificationIntimateModel
                    {
                        RegistrationIds = deviceIdArray,
                        Data = data,
                        Notification = new Notification { Title = title, Body = body }
                    };

                    request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                    response = await this.client.ExecuteAsync(request);

                    await LogAsync(data, deviceIdArray, response, ToType.IOS, type);
                }
            }

            var tokensForAndroid = deviceTokensForAndroid as string[] ?? deviceTokensForAndroid.ToArray();
            if (tokensForAndroid.Any())
            {
                var data = new IntimateData
                {
                    Message = body,
                    Type = message,
                    Id = id
                };
                var registrationIds = tokensForAndroid.Select(m => m).ToArray();

                requestBody = new PushNotificationIntimateModel
                {
                    RegistrationIds = registrationIds,
                    Data = data
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.Android, type);
            }

            return response;
        }


        /// <inheritdoc />
        public async Task<IRestResponse> IntimateAndroidAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> deviceTokensForAndroid,
            string id,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationIntimateModel requestBody;

            IRestResponse response = null;

            var tokensForAndroid = deviceTokensForAndroid as string[] ?? deviceTokensForAndroid.ToArray();
            if (tokensForAndroid.Any())
            {
                var data = new IntimateData
                {
                    Message = body,
                    Type = message,
                    Id = id
                };
                var registrationIds = tokensForAndroid.Select(m => m).ToArray();

                requestBody = new PushNotificationIntimateModel
                {
                    RegistrationIds = registrationIds,
                    Data = data
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(data, registrationIds, response, ToType.Android, type);
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> IntimateIOSAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> deviceTokensForIOS,
            string id,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationIntimateModel requestBody;

            IRestResponse response = null;

            var tokensForIOS = deviceTokensForIOS as string[] ?? deviceTokensForIOS.ToArray();
            if (tokensForIOS.Any())
            {
                var registrationIds = tokensForIOS.Select(m => m).ToArray();

                foreach (var deviceId in registrationIds)
                {
                    if (deviceId.ToUpper() == "string".ToUpper() || deviceId == "" || deviceId == null)
                    {
                        continue;
                    }

                    var deviceIdArray = new[] { deviceId };
                    var data = new IntimateData
                    {
                        Message = message,
                        Type = body,
                        Id = id
                    };
                    requestBody = new PushNotificationIntimateModel
                    {
                        RegistrationIds = deviceIdArray,
                        Data = data,
                        Notification = new Notification { Title = title, Body = body }
                    };

                    request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                    response = await this.client.ExecuteAsync(request);

                    await LogAsync(data, deviceIdArray, response, ToType.IOS, type);
                }
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendAsync(
            string title,
            string body,
            string message,
            IEnumerable<string> androidTokens,
            IEnumerable<string> iosTokens,
            object data,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            PushNotificationDataModel requestBody;

            IRestResponse response = null;

            var tokensForAndroid = androidTokens as string[] ?? androidTokens.ToArray();
            if (tokensForAndroid.Any())
            {
                var dataAlt = new NotificationData
                {
                    Message = body,
                    Content = data
                };

                var registrationIds = tokensForAndroid.Select(m => m).ToArray();
                requestBody = new PushNotificationDataModel
                {
                    RegistrationIds = registrationIds,
                    Data = dataAlt
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(dataAlt, registrationIds, response, ToType.Android, type);
            }

            var tokensForIOS = iosTokens as string[] ?? iosTokens.ToArray();
            if (tokensForIOS.Any())
            {
                var dataAlt = new NotificationData
                {
                    Message = body,
                    Content = data
                };

                var registrationIds = tokensForIOS.Select(m => m).ToArray();
                requestBody = new PushNotificationDataModel
                {
                    RegistrationIds = registrationIds,
                    Data = dataAlt,
                    Notification = new Notification
                    {
                        Title = title,
                        Body = body
                    }
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await LogAsync(dataAlt, registrationIds, response, ToType.IOS, type);
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendSingleAsync(
            string title,
            string body,
            string message,
            string deviceTokens,
            int deviceType,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var data = new Data
            {
                Message = message,
                Type = body
            };

            var requestBody = new PushNotificationRequestModelSingleDevice();
            if (deviceType == 2)
            {
                requestBody = new PushNotificationRequestModelSingleDevice
                {
                    RegistrationIds = deviceTokens,
                    Data = data
                };
            }

            if (deviceType == 3)
            {
                requestBody = new PushNotificationRequestModelSingleDevice
                {
                    RegistrationIds = deviceTokens,
                    Data = data,
                    Notification = new Notification { Title = title, Body = body }
                };
            }

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);

            var response = await this.client.ExecuteAsync(request);

            await this.LogAsync(data, new List<string> { deviceTokens }, response, deviceType == 2 ? ToType.Android : ToType.IOS, type);

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendVideoCallNotificationsAsync(string title, string body, string message, string deviceTokens, string doctorName, string doctorEmail, string deviceId, NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var data = new Data
            {
                Sinch = new
                {
                    name = message,
                    sinch = new
                    {
                        flags = 1,
                        public_headers = new { SinchIntiatorName = doctorName },
                        session_id = deviceId,
                        timestamp = 1585650460,
                        type = 1,
                        user_id = doctorEmail,
                        version = 4
                    }
                }
            };

            var requestBody = new PushNotificationRequestModelSingleDevice
            {
                RegistrationIds = deviceTokens,
                Data = data
            };

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);

            var response = await this.client.ExecuteAsync(request);

            await this.LogAsync(data, new List<string> { deviceTokens }, response, ToType.Android, type);

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendVideoCallNotificationsToAllDevicesAsync(string title, string body, string message, IEnumerable<string> deviceTokens, string doctorName, string doctorEmail, string deviceId, NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var data = new Data
            {
                Sinch = new
                {
                    name = message,
                    sinch = new
                    {
                        flags = 1,
                        public_headers = new { SinchIntiatorName = doctorName },
                        session_id = deviceId,
                        timestamp = 1585650460,
                        type = 1,
                        user_id = doctorEmail,
                        version = 4
                    }
                }
            };
            var registrationsIds = deviceTokens.Select(m => m).ToArray();
            var requestBody = new PushNotificationRequestModel
            {
                RegistrationIds = registrationsIds,
                Data = data
            };
            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);

            var response = await this.client.ExecuteAsync(request);

            await this.LogAsync(data, registrationsIds, response, ToType.Android, type);

            return response;

        }

        /// <inheritdoc />
        public async Task<IRestResponse> SendChatNotificationsAsync(string title, string body, string payload, IEnumerable<string> deviceTokensAndroid, IEnumerable<string> deviceTokensIOS, NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var chatModel = JsonConvert.DeserializeObject<ChatPushNotificationModel>(payload);
            PushNotificationRequestModel requestBody;

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            IRestResponse response = null;

            var tokensAndroid = deviceTokensAndroid as string[] ?? deviceTokensAndroid.ToArray();
            if (tokensAndroid.Any())
            {
                var data = new Data
                {
                    Chat =
                        new
                        {
                            senderId = chatModel.SenderId,
                            senderType = chatModel.SenderType,
                            receiverId = chatModel.ReceiverId,
                            receiverType = chatModel.ReceiverType,
                            message = chatModel.Message,
                            name = chatModel.Name,
                            thumbnail = chatModel.Thumbnail
                        },
                    Type = "Chat"
                };
                var registrationsIds = tokensAndroid.Select(m => m).ToArray();

                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationsIds,
                    Data = data
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await this.LogAsync(data, registrationsIds, response, ToType.Android, type);
            }

            var tokensIOS = deviceTokensIOS as string[] ?? deviceTokensIOS.ToArray();
            if (tokensIOS.Any())
            {
                var data = new Data
                {
                    Chat =
                        new
                        {
                            senderId = chatModel.SenderId,
                            senderType = chatModel.SenderType,
                            receiverId = chatModel.ReceiverId,
                            receiverType = chatModel.ReceiverType,
                            message = chatModel.Message,
                            name = chatModel.Name,
                            thumbnail = chatModel.Thumbnail
                        },
                    Type = "Chat"
                };
                var registrationsIds = tokensIOS.Select(m => m).ToArray();

                requestBody = new PushNotificationRequestModel
                {
                    RegistrationIds = registrationsIds,
                    Data = data,
                    Notification = new Notification { Title = title, Body = body }
                };

                request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                response = await this.client.ExecuteAsync(request);

                await this.LogAsync(data, registrationsIds, response, ToType.IOS, type);
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> TelemedicineCallNotification(string source, string message, List<string> deviceTokens, string doctorName, int telemedicineId, NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var data = new Data { Source = source, RoomName = message, Type = "Telemedicine", DoctorName = doctorName };
            var registrationsIds = deviceTokens.ToArray();
            var requestBody = new PushNotificationRequestModel
            {
                RegistrationIds = registrationsIds,
                Data = data
            };

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);

            var response = await this.client.ExecuteAsync(request);

            await this.LogAsync(data, registrationsIds, response, ToType.Android, type);

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> TelemedicineCallNotification(NotificationIntimateModel model, NotificationType? type = null)
        {
            IRestResponse response = null;
            foreach (var device in model.Devices)
            {
                if (device.DeviceType == 2)
                {
                    var data = new Data
                    {
                        Message = model.Message,
                        RoomName = model.RoomName,
                        Type = model.Type,
                        CallerId = model.CallerId,
                        OriginalRoomName = model.OriginalRoomName,
                        TelemedicineId = model.TelemedicineId,
                        Domain = model.DomainName
                    };

                    var registrationsIds = new[] { device.DeviceToken };
                    this.client = new RestClient(this.fcmConfiguration.URL);
                    var requestBody = new PushNotificationRequestModel
                    {
                        RegistrationIds = registrationsIds,
                        Data = data
                    };
                    var request = new RestRequest(Method.POST);
                    request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
                    request.AddHeader("Content-Type", "application/json");
                    request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                    response = await this.client.ExecuteAsync(request);

                    await this.LogAsync(data, registrationsIds, response, ToType.Android, type);
                }
                else if (device.DeviceType == 3)
                {
                    this.client = new RestClient(this.fcmConfiguration.URL);
                    var data = new Data
                    {
                        Message = model.Message,
                        RoomName = model.RoomName,
                        Type = model.Type,
                        CallerId = model.CallerId,
                        OriginalRoomName = model.OriginalRoomName,
                        TelemedicineId = model.TelemedicineId,
                        Domain = model.DomainName
                    };
                    var registrationsIds = new[] { device.DeviceToken };

                    var requestBody = new PushNotificationRequestModel
                    {
                        RegistrationIds = registrationsIds,
                        Data = data,
                        Notification = new Notification { Title = model.Title, Body = model.SubTitle, Sound = model.IsCall ? "incoming.wav" : string.Empty }
                    };
                    var request = new RestRequest(Method.POST);
                    request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
                    request.AddHeader("Content-Type", "application/json");
                    request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
                    response = await this.client.ExecuteAsync(request);

                    await this.LogAsync(data, registrationsIds, response, ToType.IOS, type);
                }
            }

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> CustomNotification(string payload)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", payload, ParameterType.RequestBody);
            var response = await this.client.ExecuteAsync(request);
            return response;
        }

        /// <summary>
        /// The frequent notify.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="device">
        /// The device.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private async Task<IRestResponse> IOSNotify(
            NotificationIntimateModel model,
            NotificationDeviceModel device,
            NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);
            var data = new Data
            {
                Message = model.Message,
                RoomName = model.RoomName,
                Type = model.Type,
                OriginalRoomName = model.OriginalRoomName,
                TelemedicineId = model.TelemedicineId,
                Domain = model.DomainName,
                StartAudioOnly = model.StartAudioOnly
            };
            var registrationsIds = new[] { device.DeviceToken };
            var notification = new Notification
            {
                Title = model.Title,
                Body = model.SubTitle,
                Sound = model.IsCall ? "incoming.wav" : string.Empty
            };

            const string collapseKey = "Call_Key";
            if (model.IsCall)
            {
                notification.Badge = 0;
                notification.Tag = collapseKey;
            }

            var requestBody = new PushNotificationRequestModel
            {
                RegistrationIds = registrationsIds,
                Data = data,
                Notification = notification,
                ContentAvailable = true
            };

            if (model.IsCall)
            {
                requestBody.CollapseKey = collapseKey;
            }

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", JsonConvert.SerializeObject(requestBody), ParameterType.RequestBody);
            var response = await this.client.ExecuteAsync(request);

            await this.LogAsync(data, registrationsIds, response, ToType.IOS, type, model.AccountId);

            return response;
        }

        /// <inheritdoc />
        public async Task<IRestResponse> TestNotification(string deviceToken, NotificationType? type = null)
        {
            this.client = new RestClient(this.fcmConfiguration.URL);

            var collapseKey = "abc";

            var requestBody = new
            {
                to = deviceToken,
                notification = new
                {
                    title = "Test Title",
                    body = "Test Body",
                    tag = collapseKey,
                    badge = 1
                },
                priority = "high"
            };
            var json = JsonConvert.SerializeObject(requestBody);
            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", this.fcmConfiguration.Authorization);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = await this.client.ExecuteAsync(request);
            return response;
        }
    }
}
