using MailKit;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using MTWorkHR.Core.Email;
using MTWorkHR.Core.Entities;
using MTWorkHR.Core.Global;
//using SendGrid;
//using SendGrid.Helpers.Mail;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace MTWorkHR.Infrastructure.EmailService
{
    public class MailSender : IMailSender
    {
        public AppSettingsConfiguration _configuration { get; }
        private readonly ILogger<MailSender> _logger;
        public MailSender(AppSettingsConfiguration configuration,ILogger<MailSender> logger) 
        {
            _configuration = configuration;
            _logger = logger;
        }
        //public async Task<bool> SendEmailGrid(EmailMessage email)
        //{
        //    var client = new SendGridClient(_configuration.MailSettings.ApiKey);
        //    var to = new EmailAddress(email.To);
        //    var from = new EmailAddress
        //    {
        //        Email = _configuration.MailSettings.FromAddress,
        //        Name = _configuration.MailSettings.FromName
        //    };
        //    email.Body = email.Body + "  /n" + email.url;
        //    var message = MailHelper.CreateSingleEmail(from, to, email.Subject, email.Body, email.Body);
        //    var response = await client.SendEmailAsync(message);

        //    return response.IsSuccessStatusCode;
        //}
        public async Task<bool> SendEmail(EmailMessage email)
        {
            var mailTo = email.To;
            var settings = _configuration.MailSettings;

            // Validate configuration settings
            if (string.IsNullOrEmpty(settings.SmtpUsername) ||
                string.IsNullOrEmpty(settings.Password) ||
                string.IsNullOrEmpty(settings.FromAddress) ||
                string.IsNullOrEmpty(settings.Host) ||
                settings.Port == 0 ||
                string.IsNullOrEmpty(mailTo))
            {
                Console.WriteLine("Invalid mail settings or recipient address.");
                return false;
            }

            // Create the email message
            var emailObj = new MimeMessage();
            emailObj.From.Add(new MailboxAddress("MTWork", settings.FromAddress)); // Display name + verified sender address
            emailObj.Sender = MailboxAddress.Parse(settings.FromAddress);
            emailObj.To.Add(MailboxAddress.Parse(mailTo));
            emailObj.Subject = email.Subject;

            // Build the email body with HTML content
            var builder = new BodyBuilder();
            var emailBody = email.Body;
            if (!string.IsNullOrEmpty(email.url))
            {
                // Use string interpolation with proper HTML escaping
                emailBody += $"Please click on <a href=\"{email.url}\">this link</a> or copy the following URL and open it: '{WebUtility.HtmlEncode(email.url)}'";
            }
            builder.HtmlBody = emailBody;
            emailObj.Body = builder.ToMessageBody();

            // Initialize SMTP client with logging
            //using var logger = new ProtocolLogger("smtp.log", append: false);
            using var smtp = new SmtpClient();
            try
            {
                _logger.LogInformation("Connecting to SMTP server {Host}:{Port} with username :[{SmtpUsername}]",
                settings.Host, settings.Port, settings.SmtpUsername);
                // Connect to Azure Communication Services SMTP server
                await smtp.ConnectAsync(settings.Host, settings.Port, SecureSocketOptions.StartTls);
                _logger.LogInformation("Authenticating with username {SmtpUsername}:[{pass}]", settings.SmtpUsername, settings.Password);
                // Authenticate using SMTP Username and Entra app client secret
                await smtp.AuthenticateAsync(settings.SmtpUsername, settings.Password);
                _logger.LogInformation("Sending email to {To} with subject {Subject}", mailTo, email.Subject);
                // Send the email
                await smtp.SendAsync(emailObj);
                _logger.LogInformation("Email sent successfully to {To}", mailTo);
            }
            catch (AuthenticationException ex)
            {
                _logger.LogError(ex, "Authentication failed for username {SmtpUsername}: {Message}",
                settings.SmtpUsername, ex.Message);
                throw ex;
                Console.WriteLine($"Authentication failed: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
                return false;
            }
            catch (SmtpCommandException ex)
            {
                _logger.LogError(ex, "SMTP error: {Message}, Status: {StatusCode}", ex.Message, ex.StatusCode);
                throw ex;
                Console.WriteLine($"SMTP error: {ex.Message}, Status: {ex.StatusCode}, Inner Exception: {ex.InnerException?.Message}");
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending email to {To}: {Message}", mailTo, ex.Message);
                throw ex;
                Console.WriteLine($"Error sending email: {ex.Message}, Inner Exception: {ex.InnerException?.Message}");
                return false;
            }
            finally
            {
                // Ensure disconnection
                if (smtp.IsConnected)
                {
                    await smtp.DisconnectAsync(true);
                    _logger.LogInformation("Disconnected from SMTP server");
                }
            }

            return true;
        }
        public async Task<bool> SendEmailSMTP(EmailMessage email)
        {
            var mailTo = email.To;
            var settings = _configuration.MailSettings;
            if (settings.FromAddress == null || settings.FromAddress== "" || settings.Password == null || settings.TemplatePath == null || settings.Host == null || settings.Port == 0 || mailTo == null)
                return false;

            //string FilePath = _configuration.MailSettings.TemplatePath;
            //StreamReader str = new StreamReader(FilePath);
            //string MailText = str.ReadToEnd();
            //str.Close();

            //MailText = MailText.Replace("[NotificationType]", email.Subject).Replace("[Info]", email.Body).Replace("[Link]", email.url );

            var emailObj = new MimeMessage();
            emailObj.From.Add(new MailboxAddress("MTWork", _configuration.MailSettings.FromAddress)); // Ensure From matches authenticated email
            emailObj.Sender = MailboxAddress.Parse(_configuration.MailSettings.FromAddress);
            emailObj.To.Add(MailboxAddress.Parse(mailTo));
            emailObj.Subject = email.Subject;

            var builder = new BodyBuilder();
            email.Body = email.Body +
                 ( string.IsNullOrEmpty( email.url ) ?"":  "Please click on <a href =\"" + email.url + "\">this link</a> or copy the following url and open it : \' " + email.url+"\'");

            builder.HtmlBody = email.Body;
            emailObj.Body = builder.ToMessageBody();
            using var logger = new ProtocolLogger("smtp.log", append: false);
            using var smtp = new SmtpClient(logger);
            try
            {
               

                smtp.Connect(_configuration.MailSettings.Host, _configuration.MailSettings.Port, MailKit.Security.SecureSocketOptions.StartTls);
                smtp.Authenticate(_configuration.MailSettings.FromAddress, _configuration.MailSettings.Password);
                await smtp.SendAsync(emailObj);
                //smtp.Disconnect(true);
            }
            catch (MailKit.Security.AuthenticationException ex)
            {
                Console.WriteLine($"Authentication failed: {ex.Message}");
                throw;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error sending email: {ex.Message}");
                throw;
            }
            finally
            {
                await smtp.DisconnectAsync(true);
            }
            return true;
        }
    }
}
