using ClaudeDo.Ui.ViewModels.Islands;

namespace ClaudeDo.Ui.Tests.ViewModels;

public class PrepPanelViewModelTests
{
    private sealed class Worker : StubWorkerClient
    {
        public TaskCompletionSource<bool> Gate { get; } = new();
        public bool Throw { get; set; }

        public override Task<bool> RunDailyPrepNowAsync() =>
            Throw ? Task.FromException<bool>(new InvalidOperationException("boom")) : Gate.Task;
    }

    [Fact]
    public async Task PlanDay_sets_PrepOperation_IsRunning_before_the_started_broadcast_arrives()
    {
        var worker = new Worker();
        var vm = new PrepPanelViewModel(worker);

        var plan = vm.PlanDayCommand.ExecuteAsync(null);

        Assert.True(vm.PrepOperation.IsRunning);
        Assert.False(vm.IsPrepRunning); // the broadcast hasn't fired yet

        worker.Gate.SetResult(true);
        await plan;

        Assert.False(vm.PrepOperation.IsRunning);
    }

    [Fact]
    public async Task PlanDayCommand_CanExecute_is_locked_while_running()
    {
        var worker = new Worker();
        var vm = new PrepPanelViewModel(worker);

        var plan = vm.PlanDayCommand.ExecuteAsync(null);
        Assert.False(vm.PlanDayCommand.CanExecute(null));
        Assert.False(vm.IsPlanDayEnabled);

        worker.Gate.SetResult(true);
        await plan;

        Assert.True(vm.PlanDayCommand.CanExecute(null));
        Assert.True(vm.IsPlanDayEnabled);
    }

    [Fact]
    public async Task PlanDay_ends_the_operation_when_the_worker_call_throws()
    {
        var worker = new Worker { Throw = true };
        var vm = new PrepPanelViewModel(worker);

        await vm.PlanDayCommand.ExecuteAsync(null);

        Assert.False(vm.PrepOperation.IsRunning);
        Assert.True(vm.PlanDayCommand.CanExecute(null));
    }
}
