using System.Diagnostics.CodeAnalysis;
using CliWrap;
using CliWrap.Buffered;
using InnovEnergy.Lib.Utils;

namespace InnovEnergy.App.Backend.S3;

[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
public class S3Cmd
{
    private static readonly Command Python = Cli.Wrap("python3");
    
    private const String? S3CmdPath    = "Resources/s3cmd.py";
    private const String S3Prefix = "s3://";
    
    public String Key       { get; init;} 
    public String Secret    { get; init;} 
    
    // private String?[] DefaultArgs { get; }

    // ReSharper disable StringLiteralTypo
    // ReSharper enable StringLiteralTypo
    [Obsolete("Only to be used by Json-Deserializer")] public S3Cmd()
    {
    }

    // public S3Cmd(String? key, String? secret)
    // {
    //     DefaultArgs = new[]
    //     {
    //         S3CmdPath,
    //         "--access_key", key,
    //         "--secret_key", secret,
    //     };
    // }
    
    public async Task<String> SignUrl(String bucketName, TimeSpan validity)
    {
        var result = await Run(bucketName, "signurl", $"+{validity.TotalSeconds}");
        
        return result
              .StandardOutput
              .Replace("\n", "")
              .Replace(" ", "");
    }
    
    public async Task<Boolean> CreateBucket(String bucketName)
    {
        var cors = @"<?xml version=""1.0"" ?>
            <CORSConfiguration xmlns=""http://s3.amazonaws.com/doc/2006-03-01/"">
            <CORSRule>
            <AllowedOrigin>*</AllowedOrigin>
            <AllowedMethod>GET</AllowedMethod>
            <AllowedMethod>HEAD</AllowedMethod>
            <AllowedHeader>*</AllowedHeader>
            </CORSRule>
            </CORSConfiguration>";
        
        var result = await Run(bucketName, "mb");
        var setCors = await Run(bucketName, "setcors", cors);
        
        return result.ExitCode == 0 && setCors.ExitCode == 0;
    }
    
    public async Task<String> ListFilesInBucket(String bucketName)
    {        
        var result = await Run(bucketName, "ls");
        return result.StandardOutput;
    }
    
    public async Task<String[]> GetFileText(String bucketName, String filename)
    {
        var result = await Run(bucketName + "/" + filename, "get", "--force");
        return File.ReadAllLines("./" + filename);
    }
    
    public async Task<Boolean> DeleteBucket(String bucketName)
    {
        var result = await Run(bucketName, "rb");
        return result.ExitCode == 0;
    }

    private Task<BufferedCommandResult> Run(String bucketName, String operation, params String[] optionalArgs)
    {
        var credentials = new String[]
        {
            S3CmdPath,
            "--access_key", Key,
            "--secret_key", Secret,
        };
            
        var args = credentials
                  .Append(operation)
                  .Append(bucketName.EnsureStartsWith(S3Prefix))
                  .Concat(optionalArgs);

        return Python
                .WithArguments(args)
                .ExecuteBufferedAsync();
    }

}