using ICSharpCode.SharpZipLib.Tar;
using k8s;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace cp;

internal class Cp
{
    private static IKubernetes client;

    private static async Task Main(string[] args)
    {
        var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
        client = new Kubernetes(config);


        var pods = client.CoreV1.ListNamespacedPod("default", null, null, null, $"job-name=upload-demo");
        var pod = pods.Items.First();

        await CopyFileToPodAsync(pod.Metadata.Name, "default", "upload-demo", args[0], $"home/{args[1]}").ConfigureAwait(false);
    }




    private static void ValidatePathParameters(string sourcePath, string destinationPath)
    {
        if (string.IsNullOrWhiteSpace(sourcePath))
        {
            throw new ArgumentException($"{nameof(sourcePath)} cannot be null or whitespace");
        }

        if (string.IsNullOrWhiteSpace(destinationPath))
        {
            throw new ArgumentException($"{nameof(destinationPath)} cannot be null or whitespace");
        }
    }

    public static async Task<int> CopyFileToPodAsync(string name, string @namespace, string container, string sourceFilePath, string destinationFilePath, CancellationToken cancellationToken = default(CancellationToken))
    {
        // All other parameters are being validated by MuxedStreamNamespacedPodExecAsync called by NamespacedPodExecAsync
        ValidatePathParameters(sourceFilePath, destinationFilePath);

        // The callback which processes the standard input, standard output and standard error of exec method
        var handler = new ExecAsyncCallback(async (stdIn, stdOut, stdError) =>
        {
            var fileInfo = new FileInfo(destinationFilePath);
            try
            {
                using (var memoryStream = new MemoryStream())
                {
                    using (var inputFileStream = File.OpenRead(sourceFilePath))
                    using (var tarOutputStream = new TarOutputStream(memoryStream, Encoding.Default))
                    {
                        tarOutputStream.IsStreamOwner = false;

                        var fileSize = inputFileStream.Length;
                        var entry = TarEntry.CreateTarEntry(fileInfo.Name);

                        entry.Size = fileSize;

                        tarOutputStream.PutNextEntry(entry);
                        await inputFileStream.CopyToAsync(tarOutputStream).ConfigureAwait(false);
                        tarOutputStream.CloseEntry();
                    }

                    memoryStream.Position = 0;

                    await memoryStream.CopyToAsync(stdIn).ConfigureAwait(false);
                    await stdIn.FlushAsync().ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                throw new IOException($"Copy command failed: {ex.Message}");
            }

            using StreamReader streamReader = new StreamReader(stdError);
            while (streamReader.EndOfStream == false)
            {
                string error = await streamReader.ReadToEndAsync().ConfigureAwait(false);
                throw new IOException($"Copy command failed: {error}");
            }
        });

        string destinationFolder = GetFolderName(destinationFilePath);

        return await client.NamespacedPodExecAsync(
            name,
            @namespace,
            container,
            new string[] { "sh", "-c", $"tar xmf - -C {destinationFolder}" },
            false,
            handler,
            cancellationToken).ConfigureAwait(false);
    }


    private static string GetFolderName(string filePath)
    {
        var folderName = Path.GetDirectoryName(filePath);

        return string.IsNullOrEmpty(folderName) ? "." : folderName;
    }
}
