using CorePush.Google;
using Hims.Api.Hubs;
using Hims.Domain.Configurations;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Hims.Api.Models.PushNotifications.Service
{
    /// <summary>
    /// NotificationService interface
    /// </summary>
    public interface INotificationService
    {
        /// <summary>
        /// Sends the notification.
        /// </summary>
        /// <param name="notificationModel">The notification model.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        Task<ResponseModel> SendNotification(NotificationModel notificationModel, DataPayload data);

        /// <summary>
        /// Sends the web notification.
        /// </summary>
        /// <param name="notificationModel">The notification model.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        Task<ResponseModel> SendWebNotification(NotificationModel notificationModel, CommunicationMessageAlt data);
    }

    /// <summary>
    /// NotificationService service
    /// </summary>
    /// <seealso cref="Hims.Api.Models.PushNotifications.Service.INotificationService" />
    public class NotificationService : INotificationService
    {
        private readonly INotificationConfiguration configuration;

        /// <summary>
        /// Initializes a new instance of the <see cref="NotificationService"/> class.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        public NotificationService(INotificationConfiguration configuration)
        {
            this.configuration = configuration;
        }

        /// <summary>
        /// Sends the notification.
        /// </summary>
        /// <param name="notificationModel">The notification model.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public async Task<ResponseModel> SendNotification(NotificationModel notificationModel, DataPayload data)
        {
            ResponseModel response = new ResponseModel();
            try
            {
                if (notificationModel.IsAndroiodDevice)
                {
                    /* FCM Sender (Android Device) */
                    var settings = new FcmSettings()
                    {
                        SenderId = this.configuration.SenderId,
                        ServerKey = this.configuration.ServerKey
                    };
                    HttpClient httpClient = new HttpClient();

                    string authorizationKey = string.Format("keyy={0}", settings.ServerKey);
                    string deviceToken = notificationModel.DeviceId;

                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorizationKey);
                    httpClient.DefaultRequestHeaders.Accept
                            .Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    DataPayload dataPayload = new DataPayload
                    {
                        Do = data.Do,
                        Type = data.Type,
                        Reason = data.Reason
                    };

                    GoogleNotification notification = new GoogleNotification
                    {
                        Data = dataPayload,
                        Notification = notificationModel
                    };

                    var fcm = new FcmSender(settings, httpClient);
                    var fcmSendResponse = await fcm.SendAsync(deviceToken, notification);

                    if (fcmSendResponse.IsSuccess())
                    {
                        response.IsSuccess = true;
                        response.Message = "Notification sent successfully";
                        return response;
                    }
                    else
                    {
                        response.IsSuccess = false;
                        response.Message = fcmSendResponse.Results[0].Error;
                        return response;
                    }
                }
                else
                {
                    /* Code here for APN Sender (iOS Device) */
                    //var apn = new ApnSender(apnSettings, httpClient);
                    //await apn.SendAsync(notification, deviceToken);
                }
                return response;
            }
            catch (Exception ex)
            {
                response.IsSuccess = false;
                response.Message = "Something went wrong";
                return response;
            }
        }

        /// <summary>
        /// Sends the web notification.
        /// </summary>
        /// <param name="notificationModel">The notification model.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public async Task<ResponseModel> SendWebNotification(NotificationModel notificationModel, CommunicationMessageAlt data)
        {
            ResponseModel response = new ResponseModel();
            try
            {
                var settings = new FcmSettings()
                {
                    SenderId = this.configuration.SenderId,
                    ServerKey = this.configuration.ServerKey
                };
                HttpClient httpClient = new HttpClient();

                string authorizationKey = string.Format("keyy={0}", settings.ServerKey);
                string deviceToken = notificationModel.DeviceId;

                httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorizationKey);
                httpClient.DefaultRequestHeaders.Accept
                        .Add(new MediaTypeWithQualityHeaderValue("application/json"));

                GoogleWebNotification notification = new GoogleWebNotification
                {
                    Data = data,
                    Notification = notificationModel
                };

                var fcm = new FcmSender(settings, httpClient);
                var fcmSendResponse = await fcm.SendAsync(deviceToken, notification);

                if (fcmSendResponse.IsSuccess())
                {
                    response.IsSuccess = true;
                    response.Message = "Notification sent successfully";
                    return response;
                }

                response.IsSuccess = false;
                response.Message = fcmSendResponse.Results[0].Error;
                return response;
            }
            catch (Exception ex)
            {
                response.IsSuccess = false;
                response.Message = "Something went wrong";
                return response;
            }
        }
    }
}
