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

namespace GerbilManagerWebAPI.Inbox
{
    /// <summary>
    /// Live Gmail reader over IMAP (App Password auth). Reads UIDs newer than the last seen,
    /// fetches envelope + Gmail thread id + the plain-text body. Gated on Julian's App Password
    /// (tests use a fake IGmailMailReader).
    /// </summary>
    public sealed class GmailMailReader : IGmailMailReader
    {
        public async Task<IReadOnlyList<MailSummary>> FetchAsync(MailConnection connection, uint sinceUid, CancellationToken ct = default)
        {
            using var client = new ImapClient();
            await client.ConnectAsync("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect, ct);
            await client.AuthenticateAsync(connection.GmailAddress, connection.AppPassword, ct);

            var folder = string.Equals(connection.Folder, "INBOX", StringComparison.OrdinalIgnoreCase)
                ? client.Inbox
                : await client.GetFolderAsync(connection.Folder, ct);
            await folder.OpenAsync(FolderAccess.ReadOnly, ct);

            var range = new UniqueIdRange(new UniqueId(sinceUid + 1), UniqueId.MaxValue);
            var uids = await folder.SearchAsync(SearchQuery.Uids(range), ct);

            const MessageSummaryItems items = MessageSummaryItems.Envelope
                | MessageSummaryItems.UniqueId
                | MessageSummaryItems.GMailThreadId
                | MessageSummaryItems.InternalDate;
            var summaries = await folder.FetchAsync(uids, items, ct);

            var result = new List<MailSummary>();
            foreach (var s in summaries)
            {
                var env = s.Envelope;
                var msg = await folder.GetMessageAsync(s.UniqueId, ct);   // body + threading headers
                var from = env?.From?.Mailboxes?.FirstOrDefault();
                result.Add(new MailSummary(
                    MessageId: env?.MessageId ?? msg.MessageId ?? "",
                    ThreadId: s.GMailThreadId?.ToString(),
                    InReplyTo: msg.InReplyTo,
                    References: msg.References is { Count: > 0 } ? string.Join(' ', msg.References) : null,
                    FromAddress: from?.Address ?? "",
                    FromName: string.IsNullOrWhiteSpace(from?.Name) ? null : from!.Name,
                    Subject: env?.Subject ?? msg.Subject,
                    BodyText: msg.TextBody,
                    ReceivedAt: s.InternalDate ?? env?.Date ?? DateTimeOffset.UtcNow,
                    Uid: s.UniqueId.Id));
            }

            await client.DisconnectAsync(true, ct);
            return result;
        }
    }
}
