using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Hotline.Share.Dtos.ExportWord;
using Hotline.Share.Tools;
using HtmlToOpenXml;
using OpenHtmlToPdf;

namespace Hotline.Application.ExportWord
{
    public static class WordHelper
    {
        public static Stream ConvertHtmlToPdf(string htmlContent)
        {
            var pdf = OpenHtmlToPdf.Pdf
                .From(htmlContent)
                .WithObjectSetting("web.defaultEncoding", "utf-8")
                .Content();
            var stream = new MemoryStream(pdf)
            {
                Position = 0
            };
            return stream;
        }

        public static Stream ConvertHtmlToWord(string htmlContent)
        {
            var memoryStream = new MemoryStream();
            using (var wordDoc = WordprocessingDocument.Create(memoryStream, DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
            {
                MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();
                mainPart.Document = new Document(new Body());

                HtmlConverter converter = new HtmlConverter(mainPart);
                var validator = new HtmlImageValidator();
                string validatedHtml = validator.ValidateAndReplaceImagesAsync(htmlContent);
                try
                {
                    var paragraphs = converter.Parse(validatedHtml);

                    foreach (var paragraph in paragraphs)
                    {
                        mainPart.Document.Body.Append(paragraph);
                    }

                    mainPart.Document.Save();
                }
                catch (Exception e)
                {
                    var msg = e.Message;
                    // ignore
                }
            }

            memoryStream.Position = 0;
            return memoryStream;
        }

        public static byte[] WordByte<T>(string templatePath, T data) where T : IWordExportTemplate
        {
            return new WordExportService(new WordExportProvider()).TemplateCreateWord(templatePath, data).WordBytes;
        }

        public static Stream WordStream<T>(string templatePath, T data) where T : IWordExportTemplate
        {
            var bytes = new WordExportService(new WordExportProvider()).TemplateCreateWord(templatePath, data).WordBytes;
            Stream stream = new MemoryStream(bytes);
            return stream;
        }

        public static bool WordDocX<T>(string templatePath, T data, string savePath) where T : IWordExportTemplate
        {
            System.IO.File.WriteAllBytes(ExistDir(savePath), WordByte(templatePath, data));
            return true;
        }

        private static string ExistDir(string path)
        {
            string text = path.Replace("\\", "/");
            if (text.IndexOf("/") > 0)
            {
                string path2 = text.Substring(0, text.LastIndexOf("/"));
                if (!Directory.Exists(path2))
                {
                    Directory.CreateDirectory(path2);
                }
            }

            return text;
        }

        /// <summary>
        /// ZipStream 压缩
        /// </summary>
        /// <param name="streams">Dictionary（string, Stream） 文件名和Stream</param>
        /// <returns></returns>
        public static byte[] ConvertZipStream(Dictionary<string, Stream> streams)
        {
            byte[] buffer = new byte[6500];
            MemoryStream returnStream = new();
            var zipMs = new MemoryStream();
            using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(zipMs))
            {
                zipStream.SetLevel(9);//设置 压缩等级 (9级 500KB 压缩成了96KB)
                foreach (var kv in streams)
                {
                    string fileName = kv.Key;
                    using (var streamInput = kv.Value)
                    {
                        ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName);
                        zipEntry.IsUnicodeText = true;
                        zipStream.PutNextEntry(zipEntry);

                        while (true)
                        {
                            var readCount = streamInput.Read(buffer, 0, buffer.Length);
                            if (readCount > 0)
                            {
                                zipStream.Write(buffer, 0, readCount);
                            }
                            else
                            {
                                break;
                            }
                        }
                        zipStream.Flush();
                    }
                }
                zipStream.Finish();
                zipMs.Position = 0;
                zipMs.CopyTo(returnStream, 5600);
            }
            returnStream.Position = 0;

            //Stream转Byte[]
            byte[] returnBytes = new byte[returnStream.Length];
            returnStream.Read(returnBytes, 0, returnBytes.Length);
            returnStream.Seek(0, SeekOrigin.Begin);

            return returnBytes;
        }
    }
}
