using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels.Modals.Settings;

namespace ClaudeDo.Ui.Tests.ViewModels;

public class PrimeClaudeTabViewModelTests
{
    private sealed class FakeApi : IPrimeScheduleApi
    {
        public List<PrimeScheduleDto> Stored { get; } = new();
        public List<PrimeScheduleDto> Upserts { get; } = new();
        public List<Guid> Deletes { get; } = new();
        public Task<List<PrimeScheduleDto>> ListAsync() => Task.FromResult(Stored.ToList());
        public Task<PrimeScheduleDto?> UpsertAsync(PrimeScheduleDto dto)
        {
            Upserts.Add(dto);
            return Task.FromResult<PrimeScheduleDto?>(dto);
        }
        public Task DeleteAsync(Guid id) { Deletes.Add(id); return Task.CompletedTask; }
    }

    private static PrimeScheduleDto Dto(Guid id, int days, TimeSpan time) =>
        new(id, days, time, true, null, null);

    [Fact]
    public async Task Load_Populates_Rows()
    {
        var api = new FakeApi();
        api.Stored.Add(Dto(Guid.NewGuid(), 31, new TimeSpan(7, 0, 0)));
        var vm = new PrimeClaudeTabViewModel(api);
        await vm.LoadAsync();
        Assert.Single(vm.Rows);
    }

    [Fact]
    public void AddSchedule_Appends_Row_With_Defaults()
    {
        var vm = new PrimeClaudeTabViewModel(new FakeApi());
        vm.AddScheduleCommand.Execute(null);
        Assert.Single(vm.Rows);
        Assert.True(vm.Rows[0].Enabled);
        Assert.True(vm.Rows[0].Monday);
        Assert.True(vm.Rows[0].Friday);
        Assert.False(vm.Rows[0].Saturday);
        Assert.Equal(new TimeSpan(7, 0, 0), vm.Rows[0].TimeOfDay);
    }

    [Fact]
    public void Row_Decomposes_And_Recomposes_Days()
    {
        var vm = new PrimeClaudeTabViewModel(new FakeApi());
        vm.AddScheduleCommand.Execute(null);
        var row = vm.Rows[0];
        Assert.Equal(31, row.DaysMask());
        row.Saturday = true;
        Assert.Equal(63, row.DaysMask());
    }

    [Fact]
    public async Task Save_Diffs_New_And_Removed_Rows()
    {
        var api = new FakeApi();
        var keptId = Guid.NewGuid();
        var deletedId = Guid.NewGuid();
        api.Stored.Add(Dto(keptId, 31, new TimeSpan(7, 0, 0)));
        api.Stored.Add(Dto(deletedId, 31, new TimeSpan(8, 0, 0)));

        var vm = new PrimeClaudeTabViewModel(api);
        await vm.LoadAsync();
        vm.RemoveScheduleCommand.Execute(vm.Rows.Single(r => r.Id == deletedId));
        vm.AddScheduleCommand.Execute(null);

        await vm.SaveAsync();

        Assert.Contains(deletedId, api.Deletes);
        Assert.Equal(2, api.Upserts.Count);
    }

    [Fact]
    public void Validate_Reports_No_Days_Selected()
    {
        var vm = new PrimeClaudeTabViewModel(new FakeApi());
        vm.AddScheduleCommand.Execute(null);
        var row = vm.Rows[0];
        row.Monday = row.Tuesday = row.Wednesday = row.Thursday = row.Friday = false;
        Assert.NotNull(vm.Validate());
    }

    [Fact]
    public void Validate_Passes_With_One_Day()
    {
        var vm = new PrimeClaudeTabViewModel(new FakeApi());
        vm.AddScheduleCommand.Execute(null);
        Assert.Null(vm.Validate());
    }
}
