using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.Extensions.Configuration;
using WorkFlowCheck.BL.Models;
using WorkFlowCheck.BL.Services.Interfaces;
using Serilog;
using WorkFlowCheck.DL.Entities;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using WorkFlowCheck.DL;
using WorkFlowCheck.Common.DTO;
using System.Net.Http.Headers;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Newtonsoft.Json;

namespace WorkFlowCheck.BL.Services
{
    public class MessageService : BaseService, IMessageService
    {
        private readonly EmailSettings _settings;

        public MessageService(AppDbContext dbContext,
                                IMapper mapper,
                                IConfiguration configuration) : base(dbContext, mapper)
        {
            _settings = configuration.GetSection("EmailSettings").Get<EmailSettings>()!;
        }

        public async Task<bool> SendMailAsync(List<string> recipients, string subject, string htmlBody, string? attachmentFilePath = null)
        {
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress(_settings.SenderName, _settings.Username));

            foreach (var recipient in recipients)
            {
                message.To.Add(MailboxAddress.Parse(recipient));
            }

            message.Subject = subject;

            var builder = new BodyBuilder
            {
                HtmlBody = htmlBody
            };

            if (!string.IsNullOrEmpty(attachmentFilePath) && File.Exists(attachmentFilePath))
            {
                builder.Attachments.Add(attachmentFilePath);
            }

            message.Body = builder.ToMessageBody();
            using var smtp = new SmtpClient();
            await smtp.ConnectAsync(_settings.SmtpServer, _settings.SmtpPort, SecureSocketOptions.StartTls);
            await smtp.AuthenticateAsync(_settings.Username, _settings.Password);
            await smtp.SendAsync(message);
            await smtp.DisconnectAsync(true);

            return true;
        }
        public async Task<bool> SendFCMTokenAsync(string token)
        {
            var retVal = true;
            try
            {
                if (!string.IsNullOrEmpty(token))
                {

                    var FCMToken = await _dbContext.FCMTokens.Where(w => w.Token == token).FirstOrDefaultAsync();
                    if (FCMToken == null)
                    {
                        FCMToken = new FCMToken();
                        FCMToken.Token = token;
                        await _dbContext.FCMTokens.AddAsync(FCMToken);
                    }
                    else
                    {
                        FCMToken.LastModAt = DateTime.UtcNow;
                    }
                    await _dbContext.SaveChangesAsync();
                }
            }
            catch (Exception ex)
            {
                retVal = false;
                Log.ForContext("TAG", "BusinessFlow").Error(ex.Message);
            }

            return retVal;
        }
        public async Task<string> GetLastFCMTokensAsync()
        {
            var retVal = "";
            try
            {
                var FCMToken = await _dbContext.FCMTokens
                                        .AsNoTracking()
                                        .OrderByDescending(x => x.LastModAt)
                                        .Take(1)
                                        .FirstOrDefaultAsync();
                if (FCMToken != null && !string.IsNullOrEmpty(FCMToken.Token))
                {
                    retVal += FCMToken.Token;
                }
            }
            catch (Exception ex)
            {
                retVal = "";
                Log.ForContext("TAG", "BusinessFlow").Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> SendFCMMessage(FCMMessageDTO fCMMessageDTO)
        {
            var retVal = true;
            try
            {
                var pathToJsonKey = "com-nuvolar-wfcapp-firebase-adminsdk-fbsvc-37642626e4.json";
                var projectId = "com-nuvolar-wfcapp";
                var credential = GoogleCredential
                                    .FromFile(pathToJsonKey)
                                    .CreateScoped("https://www.googleapis.com/auth/firebase.messaging");
                var accessToken = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();

                var client = new HttpClient();
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);


                var message = new
                {
                    message = new
                    {
                        token = fCMMessageDTO.Token,
                        notification = new
                        {
                            title = fCMMessageDTO.Title,
                            body = fCMMessageDTO.Body,
                        },
                        android = new
                        {
                            notification = new
                            {
                                channel_id = "com.nuvolar.wfcapp.general"
                            }
                        }
                    }
                };

                var json = JsonConvert.SerializeObject(message);
                var content = new StringContent(json, Encoding.UTF8, "application/json");


                var response = await client.PostAsync($"https://fcm.googleapis.com/v1/projects/{projectId}/messages:send", content);

                var result = await response.Content.ReadAsStringAsync();


            }
            catch (Exception ex)
            {
                retVal = false;
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<bool> SendFCMMessageToLastToken(FCMMessageDTO fCMMessageDTO)
        {
            var retVal = true;
            try
            {
                fCMMessageDTO.Token = await GetLastFCMTokensAsync();

                retVal = await SendFCMMessage(fCMMessageDTO);
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
    }

}
