using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Text;

namespace File_Folder_Helper.Helpers;

internal static class HelperGit
{

    private record ProcessResult(string Errors,
                                 int ExitCode,
                                 string Output);

    private static async Task<ProcessResult> RunProcessAsync(string application, string arguments, string workingDirectory, CancellationToken cancellationToken)
    {
        using Process process = new();
        StringBuilder outputBuilder = new();
        StringBuilder errorsBuilder = new();
        process.StartInfo = new ProcessStartInfo
        {
            CreateNoWindow = true,
            UseShellExecute = false,
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            FileName = application,
            Arguments = arguments,
            WorkingDirectory = workingDirectory,
        };
        process.OutputDataReceived += (_, args) => outputBuilder.AppendLine(args.Data);
        process.ErrorDataReceived += (_, args) => errorsBuilder.AppendLine(args.Data);
        _ = process.Start();
        process.BeginErrorReadLine();
        process.BeginOutputReadLine();
        await process.WaitForExitAsync(cancellationToken);
        return new(errorsBuilder.ToString().Trim(), process.ExitCode, outputBuilder.ToString().Trim());
    }

    private static async Task<string> RunAsync(string arguments, string workingDirectory, CancellationToken cancellationToken)
    {
        ProcessResult result = await RunProcessAsync("git", arguments, workingDirectory, cancellationToken);
        if (result.ExitCode != 0)
            throw new Exception($"{result.ExitCode} {result.Errors}");
        return result.Output;
    }

    internal static ReadOnlyCollection<string> GetOthersModifiedAndDeletedExcludingStandardFiles(string repositoryDirectory, bool usePathCombine, CancellationToken cancellationToken)
    {
        List<string> results = [];
        string checkDirectory = Path.Combine(repositoryDirectory, ".git");
        if (Directory.Exists(checkDirectory))
        {
            Task<string> task = RunAsync($"ls-files --others --modified --deleted --exclude-standard", repositoryDirectory, cancellationToken);
            task.Wait(cancellationToken);
            string[] files = task.Result.Split("\r\n");
            foreach (string file in files)
            {
                if (!usePathCombine)
                    results.Add(file);
                else
                    results.Add(Path.GetFullPath(Path.Combine(repositoryDirectory, file)));
            }
        }
        return new(results);
    }

}