using System;
using System.IO;
using System.Text;
using Google.Apis.Gmail.v1.Data;
using HtmlAgilityPack;
using MimeKit;
using MimeKit.IO;
using MimeKit.IO.Filters;
using MimeKit.Utils;
using Wino.Services.Extensions;

namespace Wino.Core.Extensions
{
    public static class MimeExtensions
    {
        /// <summary>
        /// Returns MimeKit.MimeMessage instance for this GMail Message's Raw content.
        /// </summary>
        /// <param name="message">GMail message.</param>
        public static MimeMessage GetGmailMimeMessage(this Message message)
        {
            if (message == null || message.Raw == null)
                return null;

            // Gmail raw is not base64 but base64Safe. We need to remove this HTML things.
            var base64Encoded = message.Raw.Replace(",", "=").Replace("-", "+").Replace("_", "/");

            byte[] bytes = Encoding.ASCII.GetBytes(base64Encoded);

            var stream = new MemoryStream(bytes);

            // This method will dispose outer stream.

            using (stream)
            {
                using var filtered = new FilteredStream(stream);
                filtered.Add(DecoderFilter.Create(ContentEncoding.Base64));

                return MimeMessage.Load(filtered);
            }
        }


        /// <summary>
        /// Sets html body replacing base64 images with cid linked resources.
        /// Updates text body based on html.
        /// </summary>
        /// <param name="bodyBuilder">Body builder.</param>
        /// <param name="htmlContent">Html content that can have embedded images.</param>
        /// <returns>Body builder with set HtmlBody.</returns>
        public static BodyBuilder SetHtmlBody(this BodyBuilder bodyBuilder, string htmlContent)
        {
            if (string.IsNullOrEmpty(htmlContent)) return bodyBuilder;

            var doc = new HtmlDocument();
            doc.LoadHtml(htmlContent);

            var imgNodes = doc.DocumentNode.SelectNodes("//img");

            if (imgNodes != null)
            {
                foreach (var node in imgNodes)
                {
                    var src = node.GetAttributeValue("src", string.Empty);

                    if (string.IsNullOrEmpty(src)) continue;

                    if (!src.StartsWith("data:image"))
                    {
                        continue;
                    }

                    var parts = src.Substring(11).Split([";base64,"], StringSplitOptions.None);

                    string mimeType = parts[0];
                    string base64Content = parts[1];

                    var alt = node.GetAttributeValue("alt", $"Embedded_Image.{mimeType}");

                    // Convert the base64 content to binary data
                    byte[] imageData = Convert.FromBase64String(base64Content);

                    // Create a new linked resource as MimePart
                    var image = new MimePart("image", mimeType)
                    {
                        ContentId = MimeUtils.GenerateMessageId(),
                        Content = new MimeContent(new MemoryStream(imageData)),
                        ContentDisposition = new ContentDisposition(ContentDisposition.Inline),
                        ContentDescription = alt.Replace(" ", "_"),
                        FileName = alt,
                        ContentTransferEncoding = ContentEncoding.Base64
                    };

                    bodyBuilder.LinkedResources.Add(image);

                    node.SetAttributeValue("src", $"cid:{image.ContentId}");
                }
            }

            bodyBuilder.HtmlBody = doc.DocumentNode.InnerHtml;

            if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody))
            {
                bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody);
            }

            return bodyBuilder;
        }
    }
}
