using System.Net.Http;
using NexusShell.Models;
using NexusShell.Services;
using NexusShell.ViewModels;
using Xunit;

namespace NexusShell.Tests;

public sealed class UpdateInfoViewModelTests
{
    [Fact]
    public void CanDownload_true_when_update_found_and_idle()
    {
        var service = CreateServiceWithUpdateFound();
        var vm = new UpdateInfoViewModel(service);

        Assert.True(vm.CanDownload);
        Assert.True(vm.CanDownloadAndInstall);
        Assert.False(vm.CanInstall);
    }

    [Fact]
    public void CanInstall_true_only_when_ready()
    {
        var service = CreateServiceWithUpdateFound();
        var vm = new UpdateInfoViewModel(service);

        SetFlowState(service, ClientUpdateFlowState.Ready);
        vm.LoadFromCache();

        Assert.False(vm.CanDownload);
        Assert.True(vm.CanInstall);
    }

    [Fact]
    public void CanClearStuck_true_when_preparing()
    {
        var service = CreateServiceWithUpdateFound();
        var vm = new UpdateInfoViewModel(service);

        SetFlowState(service, ClientUpdateFlowState.Preparing);
        vm.LoadFromCache();

        Assert.True(vm.CanClearStuck);
        Assert.False(vm.CanDownload);
    }

    [Fact]
    public void LocalBuildAhead_blocks_download_and_reports_downgrade_guard()
    {
        var service = CreateServiceWithLocalBuildAhead();
        var vm = new UpdateInfoViewModel(service);

        vm.LoadFromCache();

        Assert.True(vm.IsLocalBuildAhead);
        Assert.False(vm.IsUpdateAvailable);
        Assert.False(vm.CanDownload);
        Assert.Contains("Downgrade er blokeret", vm.InstallNotice);
        Assert.Contains("nyere lokal build", vm.StatusLabel);
    }

    private static UpdateService CreateServiceWithUpdateFound()
    {
        using var client = new HttpClient();
        var service = new UpdateService(client, "https://example.test/latest.json", "0.1.0-workspace1", 92);
        service.GetType().GetField("_lastResult", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
            .SetValue(service, new UpdateCheckResult
            {
                Status = UpdateCheckStatus.UpdateAvailable,
                IsUpdateAvailable = true,
                RemoteManifest = new NexusUpdateManifest
                {
                    Version = "0.1.0-workspace2",
                    Build = 93,
                },
            });
        SetFlowState(service, ClientUpdateFlowState.UpdateFound);
        return service;
    }

    private static UpdateService CreateServiceWithLocalBuildAhead()
    {
        using var client = new HttpClient();
        var service = new UpdateService(client, "https://example.test/latest.json", "0.1.0-osxp2", 95);
        service.GetType().GetField("_lastResult", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
            .SetValue(service, new UpdateCheckResult
            {
                Status = UpdateCheckStatus.LocalBuildAhead,
                IsUpdateAvailable = false,
                ErrorMessage = "Du kører en nyere lokal build (95) end update-kanalen (93).",
                RemoteManifest = new NexusUpdateManifest
                {
                    Version = "0.1.0-workspace2",
                    Build = 93,
                },
            });
        SetFlowState(service, ClientUpdateFlowState.UpToDate);
        return service;
    }

    private static void SetFlowState(UpdateService service, ClientUpdateFlowState state)
    {
        service.GetType().GetField("_flowState", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
            .SetValue(service, state);
    }
}
