using Deploymentcenter.Client;
using Predictalytics.Hosting;

namespace Predictalytics.Shell.Services;

/// <summary>
/// Lizenzverwaltung von der Kommandozeile — die im Deploymentcenter-Integrations-
/// leitfaden vorgesehenen Schalter. Gedacht fuer Server ohne Oberflaeche, wo es
/// keinen Aktivierungsdialog geben kann.
/// </summary>
internal static class LicenseCli
{
    public const string StatusSwitch = "--license-status";
    public const string SetKeySwitch = "--license-set-key";
    public const string DeactivateSwitch = "--license-deactivate";

    public static bool IsLicenseCommand(string[] args) =>
        args.Length > 0 && args[0] is StatusSwitch or SetKeySwitch or DeactivateSwitch;

    public static async Task<int> RunAsync(string[] args)
    {
        LicenseClient.DefaultAppVersion = DcConfig.AppVersion;

        return args[0] switch
        {
            StatusSwitch => await ShowStatusAsync(),
            SetKeySwitch => await SetKeyAsync(args.Length > 1 ? args[1] : null),
            DeactivateSwitch => await DeactivateAsync(),
            _ => HeadlessRunner.ExitFailed
        };
    }

    private static async Task<int> ShowStatusAsync()
    {
        var hw = LicenseGuard.GetHardwareInfo();
        Console.WriteLine("Predictalytics — Lizenzstatus");
        Console.WriteLine($"  Produkt      : {DcConfig.ProductSlug}");
        Console.WriteLine($"  Version      : {DcConfig.AppVersion} ({DcConfig.GitCommitShort})");
        Console.WriteLine($"  Server       : {DcConfig.BaseUrl}");
        Console.WriteLine($"  Hardware-ID  : {hw.HardwareId}");
        Console.WriteLine($"  HWID-Quelle  : {hw.HwidSource} (v{hw.HwidVersion}, {hw.Platform})");
        Console.WriteLine($"  Cache-Ablage : {LicenseGuard.StorageDirectory}");

        var cachedKey = LicenseClient.TryGetCachedKey(DcConfig.ProductSlug);
        if (string.IsNullOrWhiteSpace(cachedKey))
        {
            Console.WriteLine("  Schlüssel    : keiner hinterlegt");
            Console.WriteLine();
            Console.WriteLine($"Aktivierung: {SetKeySwitch} <SCHLÜSSEL>");
            return HeadlessRunner.ExitNoLicense;
        }

        Console.WriteLine($"  Schlüssel    : {Mask(cachedKey!)}");
        Console.WriteLine();
        Console.Write("Prüfe am Deployment Center… ");

        var check = await LicenseGuard.TryUseCachedAsync();
        var result = check.LastResult;

        if (check.IsUsable)
        {
            Console.WriteLine($"gültig ({result!.Status}{(result.IsCached ? ", aus lokalem Cache" : "")})");
            if (result.CacheExpiresAt is { } expiresAt && expiresAt > 0)
            {
                Console.WriteLine($"  Offline-Gnadenfrist bis: {DateTimeOffset.FromUnixTimeSeconds(expiresAt).UtcDateTime:yyyy-MM-dd HH:mm} UTC");
            }
            return HeadlessRunner.ExitOk;
        }

        // Transient heisst: kein Urteil, nur eine gescheiterte Verbindung.
        Console.WriteLine(result?.IsTransient == true
            ? $"unentschieden ({result.Status}): {result.Message}"
            : $"NICHT gültig ({result?.Status}): {result?.Message}");
        return HeadlessRunner.ExitNoLicense;
    }

    private static async Task<int> SetKeyAsync(string? key)
    {
        if (string.IsNullOrWhiteSpace(key))
        {
            Console.Error.WriteLine($"Aufruf: {SetKeySwitch} <SCHLÜSSEL>");
            return HeadlessRunner.ExitFailed;
        }

        Console.Write($"Aktiviere {Mask(key.Trim().ToUpperInvariant())} … ");
        var (session, result) = await LicenseGuard.ActivateAsync(LicenseGuard.CreateClient(), key);

        if (session is not null)
        {
            Console.WriteLine($"erfolgreich ({result.Status})");
            Console.WriteLine($"Hardware-ID: {result.HardwareId}");
            return HeadlessRunner.ExitOk;
        }

        Console.Error.WriteLine($"fehlgeschlagen ({result.Status}): {result.Message}");
        return HeadlessRunner.ExitNoLicense;
    }

    private static async Task<int> DeactivateAsync()
    {
        var key = LicenseClient.TryGetCachedKey(DcConfig.ProductSlug);
        if (string.IsNullOrWhiteSpace(key))
        {
            Console.Error.WriteLine("Kein hinterlegter Schlüssel — nichts zu deaktivieren.");
            return HeadlessRunner.ExitFailed;
        }

        Console.Write("Gebe Aktivierungsplatz am Deployment Center frei… ");
        var ok = await LicenseGuard.CreateClient()
            .DeactivateAsync(DcConfig.ProductSlug, key!, DcConfig.BaseUrl);
        Console.WriteLine(ok ? "erfolgreich" : "fehlgeschlagen");
        return ok ? HeadlessRunner.ExitOk : HeadlessRunner.ExitFailed;
    }

    /// <summary>Nur die Segmentstruktur zeigen, nicht den vollstaendigen Schluessel.</summary>
    private static string Mask(string key)
    {
        var parts = key.Split('-');
        if (parts.Length < 2) return "*****";
        for (var i = 1; i < parts.Length - 1; i++) parts[i] = new string('*', parts[i].Length);
        return string.Join('-', parts);
    }
}
