using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.Services.Interfaces;
using ClaudeDo.Ui.ViewModels.Islands;

namespace ClaudeDo.Ui.Tests.ViewModels;

public class NotesEditorViewModelTests
{
    private sealed class FakeNotes : INotesApi
    {
        public readonly List<DailyNoteDto> Store = new();
        private int _seq;
        public Task<List<DailyNoteDto>> ListAsync(DateOnly day) =>
            Task.FromResult(Store.Where(n => n.Date == day.ToString("yyyy-MM-dd")).ToList());
        public Task<DailyNoteDto?> AddAsync(DateOnly day, string text)
        {
            var dto = new DailyNoteDto($"id{_seq++}", day.ToString("yyyy-MM-dd"), text, Store.Count);
            Store.Add(dto);
            return Task.FromResult<DailyNoteDto?>(dto);
        }
        public Task UpdateAsync(string id, string text)
        {
            var i = Store.FindIndex(n => n.Id == id);
            if (i >= 0) Store[i] = Store[i] with { Text = text };
            return Task.CompletedTask;
        }
        public Task DeleteAsync(string id) { Store.RemoveAll(n => n.Id == id); return Task.CompletedTask; }
    }

    [Fact]
    public async Task AddBullet_PersistsAndAppears_ForCurrentDay()
    {
        var api = new FakeNotes();
        var vm = new NotesEditorViewModel(api);
        await vm.LoadDayAsync(new DateOnly(2026, 6, 1));

        vm.NewBulletText = "Standup vorbereitet";
        await vm.AddBulletCommand.ExecuteAsync(null);

        Assert.Single(vm.Bullets);
        Assert.Equal("Standup vorbereitet", vm.Bullets[0].Text);
        Assert.Equal("", vm.NewBulletText);
        Assert.Single(api.Store);
    }

    [Fact]
    public async Task PrevAndNextDay_NavigateAndReload()
    {
        var api = new FakeNotes();
        await api.AddAsync(new DateOnly(2026, 5, 31), "gestern");
        var vm = new NotesEditorViewModel(api);
        await vm.LoadDayAsync(new DateOnly(2026, 6, 1));
        Assert.Empty(vm.Bullets);

        await vm.PrevDayCommand.ExecuteAsync(null);
        Assert.Equal(new DateOnly(2026, 5, 31), vm.CurrentDay);
        Assert.Single(vm.Bullets);

        await vm.NextDayCommand.ExecuteAsync(null);
        Assert.Equal(new DateOnly(2026, 6, 1), vm.CurrentDay);
        Assert.Empty(vm.Bullets);
    }

    [Fact]
    public async Task CommitBullet_EmptyText_RemovesFromStoreAndList()
    {
        var api = new FakeNotes();
        var vm = new NotesEditorViewModel(api);
        await vm.LoadDayAsync(new DateOnly(2026, 6, 1));
        vm.NewBulletText = "weg damit";
        await vm.AddBulletCommand.ExecuteAsync(null);

        vm.Bullets[0].Text = "   ";
        await vm.CommitBulletCommand.ExecuteAsync(vm.Bullets[0]);

        Assert.Empty(vm.Bullets);
        Assert.Empty(api.Store);
    }

    [Fact]
    public async Task CommitBullet_NonEmptyText_PersistsEdit()
    {
        var api = new FakeNotes();
        var vm = new NotesEditorViewModel(api);
        await vm.LoadDayAsync(new DateOnly(2026, 6, 1));
        vm.NewBulletText = "original";
        await vm.AddBulletCommand.ExecuteAsync(null);

        vm.Bullets[0].Text = "geändert";
        await vm.CommitBulletCommand.ExecuteAsync(vm.Bullets[0]);

        Assert.Single(vm.Bullets);
        Assert.Equal("geändert", api.Store[0].Text);
    }
}
