using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RedundancyFinder;
using Spectre.Console;
using Spectre.Console.Cli;
namespace RedundancyFinderCLI
{
    internal sealed class AnalyzeCommand : Command<AnalyzeCommand.Settings>
    {
        public sealed class Settings : CommandSettings
        {
            [Description("Path to analyze.")]
            [DefaultValue("redundancies.json")]
            [CommandArgument(0, "[path]")]
            public string? Path { get; init; }

            [Description("File extensions to search for. Comma separated.")]
            [CommandOption("-e|--extensions")]
            [DefaultValue(".jpg,.webp,.raw,.pdf,.xsl,.xslx,.doc,.docx,.txt,.jpeg,.mov,.mp4,.mp3,.wav,.bmp,.gif,.png,.cu,.mid,.msb ,.mov,.avi,.wmv,.flv,.m4v,.bak ,.cpr ,.xml,.psd")]
            public string? Extensions { get; init; }

            [Description("Show all information.")]
            [CommandOption("-v|--verbose")]
            [DefaultValue(false)]
            public bool Verbose { get; init; }

        }
        public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings)
        {
            WriteLine($"[yellow]Analyzing {settings.Path}[/]");

            var redundancies = JsonConvert.DeserializeObject<Dictionary<string, Redundancy>>(File.ReadAllText(settings.Path));


            var groups = redundancies
                .GroupBy(x => Path.GetExtension(x.Value.Paths[0]), x => x.Value)
                .ToDictionary(x => x.Key, x => new
                {
                    FileSize = x.Sum(y => y.FileSize),
                    RedundancySize = x.Sum(y => y.FileSize) * (x.Sum(y => y.Paths.Count) - 1),
                    RedundancyCount = x.Sum(y => y.Paths.Count)-1,
                });
            //  x => new { FileSize = x, RedundancySize = x.Sum()*(x.Count()-1)}
            var extensions = settings.Extensions.Split(",", StringSplitOptions.RemoveEmptyEntries);
            var table = new Table();

            table.AddColumn("Type");
            table.AddColumn(new TableColumn("Size").RightAligned());
            table.AddColumn(new TableColumn("Redundancy size").RightAligned());
            table.AddColumn(new TableColumn("Redundancy count").RightAligned());
            foreach (var extension in extensions)
            {
                if (groups.ContainsKey(extension))
                {

                    var size = groups[extension].FileSize;
                    var sizeFormat = GetSizeFormat((ulong)size);

                    var redundancySize = groups[extension].RedundancySize;
                    var redundancySizeFormat = GetSizeFormat((ulong)redundancySize);
                    table.AddRow(
                        new Text(extension), 
                        new Markup($"[green]{sizeFormat}[/]"), 
                        new Markup($"[yellow]{redundancySizeFormat}[/]"),
                        new Markup($"{groups[extension].RedundancyCount}"));
                }
            }
            AnsiConsole.Write(table);
            return 0;
        }


        private void WriteLine(string v)
        {
            string now = Markup.Escape($"[{DateTime.Now.ToString("HH:mm:ss")}]");
            AnsiConsole.MarkupLine($"[gray]{now}[/] {v}");
        }

        private static string GetSizeFormat(ulong totalSize)
        {
            string sizeUnit = "B";
            double size = totalSize;
            while (size > 1024)
            {
                size /= 1024d;
                sizeUnit = sizeUnit switch
                {
                    "B" => "KB",
                    "KB" => "MB",
                    "MB" => "GB",
                    "GB" => "TB",
                    _ => sizeUnit
                };

            }
            string sizeFormat = $"{size:.00} {sizeUnit}";
            return sizeFormat;
        }
    }
}
