using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenArchival.Blazor.CustomComponents;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System.IO;

namespace OpenArchival.DataAccess.FileAccessManager;

public class ImageThumbnailer : IImageThumbnailer
{
    private readonly IOptions<FileUploadOptions> _fileUploadOptions;
    private readonly ILogger<ImageThumbnailer> _logger;

    private static readonly string[] SupportedExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff" };

    public ImageThumbnailer(IOptions<FileUploadOptions> fileUploadOptions, ILogger<ImageThumbnailer> logger)
    {
        _fileUploadOptions = fileUploadOptions;
        _logger = logger;
    }

    public async Task<ThumbnailResult> GenerateThumbnailsAsync(string originalFilePath)
    {
        if (!File.Exists(originalFilePath))
        {
            _logger.LogError("Original file not found: {Path}", originalFilePath);
            throw new FileNotFoundException("Original file not found", originalFilePath);
        }

        if (!IsSupportedImage(originalFilePath))
        {
            _logger.LogWarning("File is not a supported image format: {Path}", originalFilePath);
            return new ThumbnailResult(string.Empty, string.Empty);
        }

        var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFilePath);
        var thumbnailFolder = _fileUploadOptions.Value.ThumbnailFolderPath;

        if (!Directory.Exists(thumbnailFolder))
        {
            Directory.CreateDirectory(thumbnailFolder);
        }

        var smallPath = Path.Combine(thumbnailFolder, $"{fileNameWithoutExtension}_small.webp");
        var largePath = Path.Combine(thumbnailFolder, $"{fileNameWithoutExtension}_large.webp");

        using (var image = await Image.LoadAsync(originalFilePath))
        {
            await Task.WhenAll(
                CreateThumbnailAsync(image.Clone(x => { }), smallPath, _fileUploadOptions.Value.SmallThumbnailSize),
                CreateThumbnailAsync(image.Clone(x => { }), largePath, _fileUploadOptions.Value.LargeThumbnailSize)
            );
        }

        return new ThumbnailResult(smallPath, largePath);
    }

    public bool IsSupportedImage(string filePath)
    {
        var extension = Path.GetExtension(filePath).ToLowerInvariant();
        return SupportedExtensions.Contains(extension);
    }

    private async Task CreateThumbnailAsync(Image image, string outputPath, int maxSize)
    {
        using (image)
        {
            int width, height;
            if (image.Width > image.Height)
            {
                width = maxSize;
                height = (int)((double)image.Height / image.Width * maxSize);
            }
            else
            {
                height = maxSize;
                width = (int)((double)image.Width / image.Height * maxSize);
            }

            image.Mutate(x => x.Resize(new ResizeOptions
            {
                Size = new Size(width, height),
                Mode = ResizeMode.Max
            }));
            await image.SaveAsWebpAsync(outputPath);
        }
    }
}
