using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.External;
using ClaudeDo.Worker.Hub;
using ClaudeDo.Worker.Tests.Infrastructure;

namespace ClaudeDo.Worker.Tests.External;

public sealed class ListMcpToolsTests : IDisposable
{
    private readonly DbFixture _db = new();
    private readonly ClaudeDoDbContext _ctx;
    private readonly ListRepository _lists;
    private readonly ListMcpTools _sut;

    public ListMcpToolsTests()
    {
        _ctx = _db.CreateContext();
        _lists = new ListRepository(_ctx);
        _sut = new ListMcpTools(_lists, new HubBroadcaster(new CapturingHubContext()));
    }

    public void Dispose() { _ctx.Dispose(); _db.Dispose(); }

    [Fact]
    public async Task CreateList_PersistsWithDefaults()
    {
        var dto = await _sut.CreateList("My List", null, null, CancellationToken.None);

        Assert.Equal("My List", dto.Name);
        var loaded = await _lists.GetByIdAsync(dto.Id);
        Assert.NotNull(loaded);
        Assert.Equal("chore", loaded!.DefaultCommitType);
    }

    [Fact]
    public async Task UpdateList_PatchesNameWorkingDirAndCommitType()
    {
        var created = await _sut.CreateList("orig", null, null, CancellationToken.None);

        var dto = await _sut.UpdateList(created.Id, "renamed", "C:/work", "feat", CancellationToken.None);

        Assert.Equal("renamed", dto.Name);
        Assert.Equal("C:/work", dto.WorkingDir);
        var loaded = await _lists.GetByIdAsync(created.Id);
        Assert.Equal("feat", loaded!.DefaultCommitType);
    }

    [Fact]
    public async Task UpdateList_NotFound_Throws()
    {
        await Assert.ThrowsAsync<InvalidOperationException>(() =>
            _sut.UpdateList("missing", "x", null, null, CancellationToken.None));
    }

    [Fact]
    public async Task DeleteList_RemovesList()
    {
        var created = await _sut.CreateList("gone", null, null, CancellationToken.None);

        var result = await _sut.DeleteList(created.Id, CancellationToken.None);

        Assert.True(result.Deleted);
        Assert.Equal(created.Id, result.Id);
        Assert.Null(await _lists.GetByIdAsync(created.Id));
    }
}
