using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using MimeKit;
using WishNinja.Configuration;
using WishNinja.Data;

namespace WishNinja.Services;

/// <summary>
/// MailKit-backed sender. Implements both <see cref="IAppEmailSender"/> (invites and ad-hoc mail)
/// and Identity's <see cref="IEmailSender{TUser}"/> (confirmation/reset links). When no SMTP host
/// is configured the message is logged instead of sent, so dev/first-run works without an email
/// server.
/// </summary>
public class EmailSender(IOptions<WishNinjaOptions> options, ILogger<EmailSender> logger)
    : IAppEmailSender, IEmailSender<ApplicationUser>
{
    private readonly SmtpOptions _smtp = options.Value.Smtp;

    public async Task SendEmailAsync(string email, string subject, string htmlMessage)
    {
        if (!_smtp.IsConfigured)
        {
            logger.LogWarning(
                "SMTP not configured — email to {Email} not sent. Subject: {Subject}\n{Body}",
                email, subject, htmlMessage);
            return;
        }

        var message = new MimeMessage();
        message.From.Add(new MailboxAddress(_smtp.FromName, _smtp.FromAddress));
        message.To.Add(MailboxAddress.Parse(email));
        message.Subject = subject;
        message.Body = new BodyBuilder { HtmlBody = htmlMessage }.ToMessageBody();

        using var client = new SmtpClient();
        var socketOption = _smtp.UseStartTls ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto;
        await client.ConnectAsync(_smtp.Host!, _smtp.Port, socketOption);
        if (!string.IsNullOrWhiteSpace(_smtp.User))
        {
            await client.AuthenticateAsync(_smtp.User, _smtp.Password ?? string.Empty);
        }
        await client.SendAsync(message);
        await client.DisconnectAsync(quit: true);
        logger.LogInformation("Sent email to {Email}: {Subject}", email, subject);
    }

    // Identity IEmailSender<TUser> implementation -------------------------------------------------

    public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) =>
        SendEmailAsync(email, "Confirm your WishNinja email",
            $"Please confirm your account by <a href='{confirmationLink}'>clicking here</a>.");

    public Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink) =>
        SendEmailAsync(email, "Reset your WishNinja password",
            $"Reset your password by <a href='{resetLink}'>clicking here</a>. If you didn't request this, you can ignore this email.");

    public Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode) =>
        SendEmailAsync(email, "Reset your WishNinja password",
            $"Your password reset code is: <strong>{resetCode}</strong>");
}
