using System;
using System.Threading.Tasks;
using FoodsharingSiegen.Contracts.Model;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Options;
using MimeKit;
using MimeKit.Text;

namespace FoodsharingSiegen.Server.Service
{
    /// <summary>
    /// Default implementation of <see cref="IMailService"/> which sends emails via SMTP using MailKit.
    /// </summary>
    public class MailService : IMailService
    {
        private readonly MailSettings _mailSettings;
        private readonly TermSettings _termSettings;
        private readonly Func<ISmtpClient> _smtpClientFactory;

        /// <summary>
        /// Initializes a new instance of the <see cref="MailService"/> class.
        /// </summary>
        /// <param name="appSettings">The configured application settings injected by DI, containing the <see cref="MailSettings"/>.</param>
        public MailService(IOptions<AppSettings> appSettings, Func<ISmtpClient>? smtpClientFactory = null)
        {
            _mailSettings = appSettings.Value.Mail;
            _termSettings = appSettings.Value.Terms;
            _smtpClientFactory = smtpClientFactory ?? (() => new SmtpClient());
        }

        /// <inheritdoc/>
        public async Task SendEmailAsync(string toEmail, string subject, string htmlBody)
        {
            var email = new MimeMessage();
            email.From.Add(new MailboxAddress(_termSettings.Title, _mailSettings.FromAddress));
            email.To.Add(MailboxAddress.Parse(toEmail));
            email.Subject = subject;
            
            var textPart = new TextPart(TextFormat.Html) 
            { 
                Text = htmlBody 
            };
            email.Body = textPart;

            using var smtp = _smtpClientFactory();
            var secureOptions = _mailSettings.UseSsl ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto;
            
            await smtp.ConnectAsync(_mailSettings.Host, _mailSettings.Port, secureOptions);
            
            if (!string.IsNullOrWhiteSpace(_mailSettings.Username))
            {
                await smtp.AuthenticateAsync(_mailSettings.Username, _mailSettings.Password);
            }
            
            await smtp.SendAsync(email);
            await smtp.DisconnectAsync(true);
        }
    }
}
