using Application.Abstractions.Cache;
using Application.Abstractions.Messaging.Email;
using Application.Features.Config.Get;
using Infrastructure.Persistence;
using SharedKernel;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Infrastructure.Messaging.Email
{
    public class MailService : IMailService
    {
        private readonly ILogger<MailService> _logger;
        private readonly ICacheService _cache;
        private readonly AppSettings.SmtpSection _smtp;
        private readonly AppDbContext _db;

        // SMTP 정보
        public string Host { get; set; } = default!;
        public int Port { get; set; } = 587;
        public string? User { get; set; }
        public string? Password { get; set; }
        public bool UseStartTls { get; set; } = true;
        public string FromEmail { get; set; } = default!;
        public string FromName { get; set; } = "no-reply";

        public MailService(ILogger<MailService> logger, ICacheService cache, IOptions<AppSettings> options, AppDbContext db)
        {
            _logger = logger;
            _cache = cache;
            _smtp = options.Value.SMTP;
            _db = db;
        }

        public async Task SendAsync(SendData data, CancellationToken ct = default)
        {
            _logger.LogInformation("Sending email to {ToAddress} with subject {Subject}", data.ToAddress, data.Subject);

            // 1. Redis 캐시에서 Config 조회
            var config = await _cache.GetAsync<Response>(CacheKeys.Config, ct);
            if (config is null)
            {
                var entity = await _db.Config.AsNoTracking().OrderByDescending(x => x.ID).FirstOrDefaultAsync();
                if (entity is null)
                {
                    Host = _smtp.Host;
                    Port = _smtp.Port;
                    User = _smtp.User;
                    Password = _smtp.Password;
                    UseStartTls = _smtp.UseStartTls;
                    FromEmail = _smtp.FromEmail;
                    FromName = _smtp.FromName;
                }
                else
                {
                    Host = entity.Basic.SmtpServer ?? "";
                    Port = entity.Basic.SmtpPort ?? 587;
                    UseStartTls = entity.Basic.SmtpEnableSSL;
                    User = entity.Basic.SmtpUsername;
                    Password = entity.Basic.SmtpPassword;
                    FromEmail = entity.Basic.FromEmail ?? "";
                    FromName = entity.Basic.FromName ?? "";
                }
            } 
            else
            {
                Host = config.Basic.SmtpServer!;
                Port = config.Basic.SmtpPort! ?? 587;
                UseStartTls = config.Basic.SmtpEnableSSL;
                User = config.Basic.SmtpUsername;
                Password = config.Basic.SmtpPassword;
                FromEmail = config.Basic.FromEmail!;
                FromName = config.Basic.FromName!;
            }
           
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress(FromName, FromEmail));
            message.To.Add(MailboxAddress.Parse(data.ToAddress));
            message.Subject = data.Subject;

            var body = new BodyBuilder
            {
                HtmlBody = data.MessageHtml,
                TextBody = data.MessageText
            };

            message.Body = body.ToMessageBody();

            using var client = new SmtpClient();
            var secure = UseStartTls ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto;

            await client.ConnectAsync(Host, Port, secure, ct);

            if (!string.IsNullOrWhiteSpace(User))
            {
                await client.AuthenticateAsync(User, Password, ct);
            }

            await client.SendAsync(message, ct);
            await client.DisconnectAsync(true, ct);

            _logger.LogInformation("Email sent to {ToAddress} with subject {Subject}", data.ToAddress, data.Subject);
        }
    }
}