using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;

namespace ScadaLink.NotificationService;

/// <summary>
/// WP-11: MailKit-based SMTP client wrapper.
/// Supports OAuth2 Client Credentials (M365) and Basic Auth.
/// BCC delivery, plain text.
/// </summary>
public class MailKitSmtpClientWrapper : ISmtpClientWrapper, IDisposable
{
    private readonly SmtpClient _client = new();

    public async Task ConnectAsync(string host, int port, bool useTls, CancellationToken cancellationToken = default)
    {
        var secureSocket = useTls ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto;
        await _client.ConnectAsync(host, port, secureSocket, cancellationToken);
    }

    public async Task AuthenticateAsync(string authType, string? credentials, CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrEmpty(credentials))
            return;

        switch (authType.ToLowerInvariant())
        {
            case "basic":
                var parts = credentials.Split(':', 2);
                if (parts.Length == 2)
                {
                    await _client.AuthenticateAsync(parts[0], parts[1], cancellationToken);
                }
                break;

            case "oauth2":
                // OAuth2 token is passed directly as credentials (pre-fetched by token service)
                var oauth2 = new SaslMechanismOAuth2("", credentials);
                await _client.AuthenticateAsync(oauth2, cancellationToken);
                break;
        }
    }

    public async Task SendAsync(string from, IEnumerable<string> bccRecipients, string subject, string body, CancellationToken cancellationToken = default)
    {
        var message = new MimeMessage();
        message.From.Add(MailboxAddress.Parse(from));

        foreach (var recipient in bccRecipients)
        {
            message.Bcc.Add(MailboxAddress.Parse(recipient));
        }

        message.Subject = subject;
        message.Body = new TextPart("plain") { Text = body };

        await _client.SendAsync(message, cancellationToken);
    }

    public async Task DisconnectAsync(CancellationToken cancellationToken = default)
    {
        if (_client.IsConnected)
        {
            await _client.DisconnectAsync(true, cancellationToken);
        }
    }

    public void Dispose()
    {
        _client.Dispose();
    }
}
