using System.Text;
using System;
using ImageConvertService.ExceptionHandling;
using ImageMagick;
using ImageMagick.Formats;
using ImageConvertService.Biz.Models;

namespace ImageConvertService.Biz;

public class ImageConverter
{
    private static readonly WebPWriteDefines WebPDefines = new()
    {
        Lossless = false,
        Method = 6,
    };

    public byte[] ConvertToWebp(byte[] imageBytes)
    {
        MagickImage image;
        try
        {
            image = new MagickImage(imageBytes);
        }
        catch (Exception e)
        {
            throw new UserFriendlyException("error on reading file", e);
        }

        using var ms = new MemoryStream();
        image.Format = MagickFormat.WebP;
        image.Quality = 85;
        try
        {
            image.Write(ms, WebPDefines);
        }
        catch (Exception e)
        {
            throw new UserFriendlyException("error on writing file", e);
        }

        image.Dispose();

        return ms.ToArray();
    }

    public bool ConvertToWebp(List<ArchiveEntry> entries)
    {
        var lstExceptions = new List<(string pathAndName, Exception exception)>();

        Parallel.ForEach(entries, item =>
        {
            if (item.PathAndName.EndsWith(".webp", StringComparison.OrdinalIgnoreCase)) return;

            try
            {
                item.Content = ConvertToWebp(item.Content);
            }
            catch (Exception e)
            {
                lock (lstExceptions) lstExceptions.Add((item.PathAndName, e));
                return;
            }

            item.PathAndName += ".webp";
        });

        if (lstExceptions.Count == 0) return true;

        entries.Add(new ArchiveEntry
        {
            PathAndName = $"@{nameof(ImageConverter)}.{nameof(ConvertToWebp)}.{lstExceptions.Count}.Errors.{Guid.NewGuid():N}.txt",
            Content = Encoding.UTF8.GetBytes(
                string.Join($"{Environment.NewLine}{Environment.NewLine}",
                    lstExceptions.Select(p => $"{p.pathAndName}:{Environment.NewLine} {p.exception}"))
            )
        });

        return false;
    }
}