using ClaudeDo.Installer.Checks;
using ClaudeDo.Installer.Core;
using ClaudeDo.Installer.Pages.InstallPage;
using ClaudeDo.Installer.Pages.PathsPage;
using ClaudeDo.Installer.Pages.ServicePage;
using ClaudeDo.Installer.Pages.SystemCheckPage;
using ClaudeDo.Installer.Pages.UiSettingsPage;
using ClaudeDo.Installer.Pages.WelcomePage;
using ClaudeDo.Installer.Tests.Core;
using ClaudeDo.Installer.Tests.Pages.SystemCheckPage;
using ClaudeDo.Installer.Views;
using Microsoft.Extensions.DependencyInjection;

namespace ClaudeDo.Installer.Tests;

public class WizardViewModelTests
{
    private static IReadOnlyList<IInstallerPage> BuildAllPages(InstallContext context)
    {
        var emptyServiceProvider = new ServiceCollection().BuildServiceProvider();
        return new IInstallerPage[]
        {
            new WelcomePageViewModel(context),
            new SystemCheckPageViewModel(context, () => throw new InvalidOperationException("not needed for this test"), TestClaudeHelpLauncher.Create()),
            new PathsPageViewModel(context),
            new ServicePageViewModel(context),
            new UiSettingsPageViewModel(context),
            new InstallPageViewModel(context, emptyServiceProvider),
        };
    }

    [Fact]
    public void FreshInstall_includes_SystemCheckPage_directly_after_welcome()
    {
        var context = new InstallContext { Mode = InstallerMode.FreshInstall };
        var resolver = new PageResolver(BuildAllPages(context));
        var vm = new WizardViewModel(resolver, context, new FakeLocalizer());

        var pages = vm.Pages.ToList();
        var welcomeIndex = pages.FindIndex(p => p is WelcomePageViewModel);
        var systemCheckIndex = pages.FindIndex(p => p is SystemCheckPageViewModel);

        Assert.NotEqual(-1, welcomeIndex);
        Assert.Equal(welcomeIndex + 1, systemCheckIndex);
    }

    [Fact]
    public void Update_mode_does_not_show_SystemCheckPage()
    {
        var context = new InstallContext { Mode = InstallerMode.Update };
        var resolver = new PageResolver(BuildAllPages(context));
        var vm = new WizardViewModel(resolver, context, new FakeLocalizer());

        Assert.DoesNotContain(vm.Pages, p => p is SystemCheckPageViewModel);
    }

    [Fact]
    public async Task CanGoNext_is_false_while_the_system_check_page_has_a_blocking_error_and_true_after_a_clean_recheck()
    {
        var context = new InstallContext { Mode = InstallerMode.FreshInstall };
        var callNumber = 0;
        var systemCheckPage = new SystemCheckPageViewModel(context, () =>
        {
            callNumber++;
            IEnvironmentCheck check = callNumber == 1
                ? FakeEnvironmentCheck.Fail("git", CheckSeverity.Error)
                : FakeEnvironmentCheck.Ok("git");
            return new EnvironmentCheckService(new[] { check });
        }, TestClaudeHelpLauncher.Create());

        var resolver = new PageResolver(new IInstallerPage[]
        {
            new WelcomePageViewModel(context),
            systemCheckPage,
        });
        var vm = new WizardViewModel(resolver, context, new FakeLocalizer());

        await vm.GoNextCommand.ExecuteAsync(null); // Welcome -> SystemCheck; auto-run fails

        Assert.Same(systemCheckPage, vm.CurrentPage);
        Assert.False(vm.CanGoNext);

        await systemCheckPage.RunChecksCommand.ExecuteAsync(null); // recheck comes back clean

        Assert.True(vm.CanGoNext);
    }
}
