using System.Reflection;
using System.Text;
using InnovEnergy.Lib.Utils;
using InnovEnergy.Lib.Victron.VictronVRM;
using static System.Globalization.CompareOptions;

namespace InnovEnergy.App.RemoteSupportConsole;

// dotnet publish -c release -r ubuntu-x64
// dotnet publish RemoteSupportConsole.csproj -c Release -r linux-x64 -p:PublishSingleFile=true --self-contained true 

public static class Program
{
    public static async Task<Int32> Main(String[] args)
    {
        Console.WriteLine();

        var options          = args.Where(IsOption).Select(a => a.Trim('-').ToLower()).ToList();
        var installationName = args.LastOrDefault(a => !a.IsOption()) ?? "";  
        
        if (options.Contains("h") || options.Contains("help"))
        {
            PrintUsage();
            return 0;
        }

        var vrm = VrmAccount.Token(Login.UserId, Login.Token);
      
        var installations = await VrmInfo.GetInstallations(vrm);

        // await DumpInstallations(installations);

        var chosenInstallation = installations.ChooseInstallation(installationName);
        
        if (!chosenInstallation.HasValue)
            return 0;

        var installation = chosenInstallation.Value;

        var details      = await installation.GetDetails();
        var useVrmTunnel = options.Contains("vrm");

        var connection = useVrmTunnel
                       ? VrmConnection.Open(installation, details)
                       : VpnConnection.Open(installation, details);
        
        return await connection;
    }

    

    private static void PrintUsage()
    {
        var asm = Assembly.GetExecutingAssembly().GetName().Name;

        Console.WriteLine();
        Console.WriteLine($"Usage: {asm} [--vpn|--vrm] [InstallationName]");
        Console.WriteLine("                                                                    ");
        Console.WriteLine("       --vpn        use InnovEnergy VPN to connect (default)        "); 
        Console.WriteLine("       --vrm        use Victron remote support to connect           ");
        Console.WriteLine("                                                                    ");
        Console.WriteLine("       InstallationName can be omitted or partial (case insensitive)");
        Console.WriteLine();
    }

    private static Installation? ChooseInstallation(this IReadOnlyList<Installation> chooseFrom,
                                                                              String installationName)
    {
        
        // IgnoreNonSpace: u==ΓΌ, ignore umlauts and the like
        Boolean Match(Installation i) => i.Name.Contains(installationName, IgnoreCase | IgnoreSymbols | IgnoreNonSpace);

        var matchingInstallations = chooseFrom
                                   .Where(Match)
                                   .ToList();

        if (matchingInstallations.Count == 1)
            return matchingInstallations.First(); // found a single match, return it

        var input = matchingInstallations.Count > 0 ? installationName : "";

        // zero or more than 1 found, let user choose
        var iName = "Select installation:".ChooseFrom(chooseFrom.Select(i=>i.Name), input);

        if (chooseFrom.All(i => i.Name != iName))
            return null;

        return chooseFrom.First(i => i.Name == iName);
    }

    private static Boolean IsOption(this String arg) => arg.StartsWith("-");
    
    // DEBUG
    private static async Task DumpInstallations(IReadOnlyList<Installation> installations)
    {
        const String vrmLink = "https://vrm.victronenergy.com/installation/";

        var sb = new StringBuilder();


        var header = new[]
        {
            "Name Installation",
            "Kunde",
            "Ort",
            "Region",
            "Firma",
            "Auftragsnummer",
            "Erste Inbetriebnahme",
            "VRM Id",
            "VRM Link",
            "Geraet Typ",
            "Geraet Name",
            "Geraete Serienummer",
            "Firmware Version"
        };

        sb.AppendLine(header.JoinWith("$"));

        foreach (var i in installations)
        {
            var devices = await i.GetDevices();
            
            foreach (var device in devices)
            {
                var x = i.Name.Split('|');
                var nameLocation = x.FirstOrDefault()?.Split(',', 2);

                var customer = nameLocation?.FirstOrDefault()?.Replace("IBN", "").Trim("_ ".ToCharArray()) ?? "";
                var locationRegion = nameLocation?.LastOrDefault()?.Trim() ?? "";
                var location = locationRegion.Split("/").FirstOrDefault()?.Trim() ?? "";
                var region = locationRegion.Split("/").LastOrDefault()?.Trim() ?? "";

                var company = x.LastOrDefault()?.Split('(').FirstOrDefault()?.Trim() ?? "";
                var sn = x.LastOrDefault()?.Split('(').LastOrDefault()?.Trim("() ".ToCharArray()) ?? "";

                var created = i.Created.ToUtcDateTime().ToString("dd.MM.yyyy HH:mm");

                var line = new[]
                {
                    i.Name,
                    customer,
                    location,
                    region,
                    company,
                    sn,
                    created,
                    i.UniqueId,
                    vrmLink + i.IdSite,
                    device.Type,
                    device.ProductName,
                    device.SerialNumber,
                    device.FirmwareVersion
                };

                sb.AppendLine(line.JoinWith("$").WriteLine());
            }
        }

        File.WriteAllText("Installations.csv", sb.ToString());
    }
}