using Minio.DataModel.Args;
using Minio;
using System.Security.Cryptography;
using Minio.DataModel.Encryption;
using System;
using Modules.Media.Api.Models;
using MediatR;
using System.IO;
using static System.Runtime.InteropServices.JavaScript.JSType;
using Minio.DataModel;

namespace Modules.Media.Api.Commands;

public class AddObjectCommand : IRequest<string>
{
    public string? ObjectName { get; set; }
    public string BusketName { get; set; } = default!;
    public string ObjectPrefix { get; set; } = default!;
    public string ObjectExtension { get; set; } = default!;
    public string ContentType { get; set; } = default!;
    public Stream Data { get; set; } = default!;
}

public class AddObjectCommandHandler(IMinioClient client) : IRequestHandler<AddObjectCommand, string>
{
    public async Task<string> Handle(AddObjectCommand request, CancellationToken cancellationToken)
    {
        //Aes aesEncryption = Aes.Create();
        //aesEncryption.KeySize = 256;
        //aesEncryption.GenerateKey();
        //var ssec = new SSEC(aesEncryption.Key);

        //var args = new GetObjectArgs()
        //    .WithBucket("my-bookmark.account")
        //    .WithMatchETag(objectId)
        //    .WithCallbackStream((stream) =>
        //    {
        //        stream.CopyTo(Console.OpenStandardOutput());
        //    });
        var contentType = !string.IsNullOrWhiteSpace(request.ContentType) ? request.ContentType : "application/octet-stream";
        var args = new PutObjectArgs()
            .WithBucket(request.BusketName)
            .WithStreamData(request.Data)
            .WithObjectSize(request.Data.Length)
            .WithContentType(contentType)
            //.WithServerSideEncryption(ssec);
            ;

        ObjectStat? existingObjectStat = null;
        if (!string.IsNullOrWhiteSpace(request.ObjectName))
        {
            existingObjectStat = await client.StatObjectAsync(new StatObjectArgs()
                .WithBucket(request.BusketName)
                .WithObject(request.ObjectName));
        }

        if (!string.IsNullOrWhiteSpace(request.ObjectName) && (existingObjectStat == null ||
            Path.GetExtension(request.ObjectName) == Path.GetExtension(existingObjectStat?.ObjectName)))
        {
            args = args.WithObject(request.ObjectName);
        }
        else
        {
            var name = string.Concat(request.ObjectPrefix, "_", Guid.NewGuid(), ".", request.ObjectExtension.TrimStart('.'));
            args = args.WithObject(name);
        }
        //var contentType = !string.IsNullOrWhiteSpace(request.ContentType) ? request.ContentType : "application/octet-stream";
        //var args = new PutObjectArgs()
        //                              .WithBucket(request.BusketName)
        //                              .WithObject(name)
        //                              .WithStreamData(request.Data)
        //                              .WithObjectSize(request.Data.Length)
        //                              .WithContentType(contentType)
        //                              //.WithServerSideEncryption(ssec);
        //                              ;

        if (!await client.BucketExistsAsync(new BucketExistsArgs().WithBucket(request.BusketName)))
        {
            throw new Exception("Busket is not exists");
        }
        
        var result = await client.PutObjectAsync(args);
        var statObjectArgs = new StatObjectArgs()
            .WithBucket(request.BusketName)
            .WithObject(result.ObjectName);
        var stat = await client.StatObjectAsync(statObjectArgs, cancellationToken);
        return result.ObjectName;
    }
}