using MailKit;
using MailKit.Net.Imap;
using MailKit.Search;
using MailKit.Security;
using MimeKit;

namespace Service.EmailServices;

/// <summary>
/// 邮件抓取服务接口
/// </summary>
public interface IEmailFetchService
{
    /// <summary>
    /// 连接状态
    /// </summary>
    bool IsConnected { get; }

    /// <summary>
    /// 连接到邮件服务器
    /// </summary>
    Task<bool> ConnectAsync(string host, int port, bool useSsl, string email, string password);

    /// <summary>
    /// 从收件箱获取未读邮件
    /// </summary>
    Task<List<(MimeMessage Message, UniqueId Uid)>> FetchUnreadMessagesAsync();

    /// <summary>
    /// 获取所有邮件
    /// </summary>
    Task<List<(MimeMessage Message, UniqueId Uid)>> FetchAllMessagesAsync();

    /// <summary>
    /// 断开与邮件服务器的连接
    /// </summary>
    Task DisconnectAsync();

    /// <summary>
    /// 标记邮件为已读
    /// </summary>
    Task MarkAsReadAsync(UniqueId uid);

    /// <summary>
    /// 确保连接有效，如断开则自动重连
    /// </summary>
    Task<bool> EnsureConnectedAsync();
}

/// <summary>
/// 邮件抓取服务实现
/// </summary>
public class EmailFetchService(ILogger<EmailFetchService> logger) : IEmailFetchService
{
    private ImapClient? _imapClient;
    private string _host = string.Empty;
    private int _port;
    private bool _useSsl;
    private string _email = string.Empty;
    private string _password = string.Empty;
    private DateTime _lastKeepAlive = DateTime.MinValue;
    private const int KeepAliveIntervalSeconds = 300; // 5分钟发送一次KeepAlive
    private readonly ILogger<EmailFetchService> _logger = logger;

    public bool IsConnected => _imapClient?.IsConnected == true;

    public async Task<bool> ConnectAsync(string host, int port, bool useSsl, string email, string password)
    {
        try
        {
            // 保存连接信息用于自动重连
            _host = host;
            _port = port;
            _useSsl = useSsl;
            _email = email;
            _password = password;
        
            // 如果已连接，先断开
            if (_imapClient?.IsConnected == true)
            {
                await DisconnectAsync();
            }
        
            _imapClient = new ImapClient();

            if (useSsl)
            {
                await _imapClient.ConnectAsync(host, port, SecureSocketOptions.SslOnConnect);
            }
            else
            {
                await _imapClient.ConnectAsync(host, port, SecureSocketOptions.StartTlsWhenAvailable);
            }

            await _imapClient.AuthenticateAsync(email, password);
            _logger.LogInformation("邮箱 {Email} 连接成功", email);
            _lastKeepAlive = DateTime.UtcNow;
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "邮件连接失败 ({Email}): {Message}", email, ex.Message);
            return false;
        }
    }

    public async Task<List<(MimeMessage Message, UniqueId Uid)>> FetchUnreadMessagesAsync()
    {
        var result = new List<(MimeMessage, UniqueId)>();

        try
        {
            // 确保连接有效
            if (!await EnsureConnectedAsync())
                return result;

            var inbox = _imapClient?.Inbox;
            if (inbox == null)
                return result;

            await inbox.OpenAsync(FolderAccess.ReadWrite);

            // 查询未读邮件
            var unreadUids = await inbox.SearchAsync(SearchQuery.NotSeen);

            foreach (var uid in unreadUids)
            {
                var message = await inbox.GetMessageAsync(uid);
                result.Add((message, uid));
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取未读邮件失败: {Message}", ex.Message);
            return result;
        }
    }

    public async Task<List<(MimeMessage Message, UniqueId Uid)>> FetchAllMessagesAsync()
    {
        var result = new List<(MimeMessage, UniqueId)>();

        try
        {
            // 确保连接有效
            if (!await EnsureConnectedAsync())
                return result;

            var inbox = _imapClient?.Inbox;
            if (inbox == null)
                return result;

            await inbox.OpenAsync(FolderAccess.ReadWrite);

            var uids = await inbox.SearchAsync(SearchQuery.All);

            foreach (var uid in uids)
            {
                var message = await inbox.GetMessageAsync(uid);
                result.Add((message, uid));
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取所有邮件失败: {Message}", ex.Message);
            return result;
        }
    }

    public async Task DisconnectAsync()
    {
        try
        {
            if (_imapClient?.IsConnected == true)
            {
                await _imapClient.DisconnectAsync(true);
                _logger.LogInformation("邮箱 {Email} 已断开连接", _email);
            }

            _imapClient?.Dispose();
            _imapClient = null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "断开连接失败 ({Email}): {Message}", _email, ex.Message);
        }
    }

    public async Task MarkAsReadAsync(UniqueId uid)
    {
        try
        {
            if (!await EnsureConnectedAsync())
                return;

            var inbox = _imapClient?.Inbox;
            if (inbox == null)
                return;

            // 打开收件箱以读写模式
            await inbox.OpenAsync(FolderAccess.ReadWrite);

            // 标记邮件为已读（设置Seen标记）
            await inbox.AddFlagsAsync(uid, MessageFlags.Seen, silent: false);
        
            _logger.LogDebug("邮件 {Uid} 标记已读操作已提交", uid);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "标记邮件为已读失败: {Message}", ex.Message);
        }
    }

    /// <summary>
    /// 确保连接有效，如果断开则自动重连
    /// </summary>
    public async Task<bool> EnsureConnectedAsync()
    {
        if (_imapClient?.IsConnected == true)
        {
            // 定期发送NOOP保持连接活跃（防止超时断开）
            var timeSinceLastKeepAlive = (DateTime.UtcNow - _lastKeepAlive).TotalSeconds;
            if (timeSinceLastKeepAlive > KeepAliveIntervalSeconds)
            {
                try
                {
                    await _imapClient.NoOpAsync();
                    _lastKeepAlive = DateTime.UtcNow;
                    _logger.LogDebug("邮箱 {Email} KeepAlive 保活信号已发送", _email);
                }
                catch (Exception ex)
                {
                    // NOOP失败，说明连接已断开，继续重连逻辑
                    _logger.LogWarning(ex, "KeepAlive 失败，连接已断开: {Message}", ex.Message);
                }
            }
            return _imapClient?.IsConnected == true;
        }
        
        if (string.IsNullOrEmpty(_host) || string.IsNullOrEmpty(_email))
        {
            _logger.LogWarning("未初始化连接信息，无法自动重连");
            return false;
        }
    
        _logger.LogInformation("检测到连接断开，尝试重新连接到 {Email}...", _email);
        return await ConnectAsync(_host, _port, _useSsl, _email, _password);
    }
}
