using System.Text;
using System.Drawing;
using IWS5.Server.Enums;
using Syncfusion.HtmlConverter;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Parsing;
using Syncfusion.PdfToImageConverter;

namespace IWS5.Server.Utils.Converter.TiffConverter;

internal class HtmlFileToTiffConverter : IFileConverter
{
    private static readonly HashSet<string> Extensions = new(StringComparer.OrdinalIgnoreCase)
    {
        nameof(ConvertibleFileTypes.html).ToLowerInvariant()
    };

    public bool CanConvert(string sourceFileExtension, string targetFileExtension) => Extensions.Contains(sourceFileExtension) && 
        string.Equals(targetFileExtension, nameof(ConvertibleFileTypes.tiff), StringComparison.OrdinalIgnoreCase);

    public async Task<byte[]> ConvertAsync(byte[] inputFile)
    {
        try
        {
            string htmlContent = Encoding.UTF8.GetString(inputFile);
            if (string.IsNullOrWhiteSpace(htmlContent))
                throw new ArgumentException("HTML content cannot be null or empty.");

            // Convert HTML to images more efficiently
            var bitmaps = await ConvertHtmlToImagesAsync(htmlContent);
            
            if (bitmaps == null || bitmaps.Length == 0)
                throw new InvalidOperationException("Failed to convert HTML to images.");

            try
            {
                return await TiffUtilities.CreateMultiPageTiffAsync(bitmaps);
            }
            finally
            {
                foreach (var bitmap in bitmaps)
                    bitmap?.Dispose();
            }
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"Error converting HTML to TIFF: {ex.Message}", ex);
        }
    }

    private async Task<Bitmap[]> ConvertHtmlToImagesAsync(string htmlContent, int dpi = 200)
    {
        try
        {
            var htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.Blink);
            htmlConverter.ConverterSettings.EnableJavaScript = true;
            htmlConverter.ConverterSettings.EnableHyperLink = false;
            htmlConverter.ConverterSettings.Margin = new PdfMargins { Top = 0, Bottom = 0, Left = 0, Right = 0 };

           using var pdfDocument = htmlConverter.Convert(htmlContent, "about:blank");
           if (pdfDocument == null)
                throw new InvalidOperationException("Failed to convert HTML to PDF.");

            using var pdfStream = new MemoryStream();
            pdfDocument.Save(pdfStream);
            pdfDocument.Close(true);
            
            pdfStream.Position = 0;
            using var pdfLoadedDoc = new PdfLoadedDocument(pdfStream);
            
            var imageStreams = new List<Stream>();
            var bitmaps = new List<Bitmap>();
            
            pdfStream.Position = 0;
            var pdfToImageConverter = new PdfToImageConverter(pdfStream);
            
            for (int pageIndex = 0; pageIndex < pdfLoadedDoc.Pages.Count; pageIndex++)
            {
                var imageStream = pdfToImageConverter.Convert(pageIndex, true, false);
                if (imageStream != null)
                {
                    imageStreams.Add(imageStream);
                    var bitmap = new Bitmap(imageStream);
                    bitmap.SetResolution(dpi, dpi);
                    bitmaps.Add(bitmap);
                }
            }

            // Dispose streams
            foreach (var stream in imageStreams)
                stream?.Dispose();

            return bitmaps.ToArray();
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"Error converting HTML to images: {ex.Message}", ex);
        }
    }
}