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

namespace ClaudeDo.Worker.Tests.Repositories;

public sealed class ListRepositoryConfigTests : IDisposable
{
    private readonly DbFixture _db = new();
    private readonly ClaudeDoDbContext _ctx;
    private readonly ListRepository _repo;
    private readonly string _listId;

    public ListRepositoryConfigTests()
    {
        _ctx = _db.CreateContext();
        _repo = new ListRepository(_ctx);
        _listId = Guid.NewGuid().ToString();
        _repo.AddAsync(new ListEntity
        {
            Id = _listId, Name = "Test", CreatedAt = DateTime.UtcNow
        }).GetAwaiter().GetResult();
    }

    [Fact]
    public async Task GetConfig_Returns_Null_When_No_Config()
    {
        var config = await _repo.GetConfigAsync(_listId);
        Assert.Null(config);
    }

    [Fact]
    public async Task SetConfig_And_GetConfig_Roundtrips()
    {
        var config = new ListConfigEntity
        {
            ListId = _listId,
            Model = "sonnet-4-6",
            SystemPrompt = "You are helpful.",
            AgentPath = "/home/user/.todo-app/agents/dev.md",
        };
        await _repo.SetConfigAsync(config);

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("sonnet-4-6", fetched.Model);
        Assert.Equal("You are helpful.", fetched.SystemPrompt);
        Assert.Equal("/home/user/.todo-app/agents/dev.md", fetched.AgentPath);
    }

    [Fact]
    public async Task SetConfig_Upserts_On_Duplicate()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, Model = "opus-4-6" });
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, Model = "haiku-4-5" });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("haiku-4-5", fetched.Model);
    }

    [Fact]
    public async Task SetConfig_Persists_SessionSkills_On_Insert()
    {
        await _repo.SetConfigAsync(new ListConfigEntity
        {
            ListId = _listId,
            SessionSkills = "[\"ponytail\"]",
        });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("[\"ponytail\"]", fetched.SessionSkills);
    }

    [Fact]
    public async Task SetConfig_Persists_SessionSkills_On_Update()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"a\"]" });
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"b\",\"c\"]" });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("[\"b\",\"c\"]", fetched.SessionSkills);
    }

    [Fact]
    public async Task SetConfig_Null_SessionSkills_Clears_On_Update()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = "[\"a\"]" });
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, SessionSkills = null });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Null(fetched.SessionSkills);
    }

    [Fact]
    public async Task SetConfig_Persists_VerifyCommand_On_Insert()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, VerifyCommand = "dotnet test" });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("dotnet test", fetched.VerifyCommand);
    }

    [Fact]
    public async Task SetConfig_Persists_VerifyCommand_On_Update()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, VerifyCommand = "dotnet build" });
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, VerifyCommand = "dotnet test" });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Equal("dotnet test", fetched.VerifyCommand);
    }

    [Fact]
    public async Task SetConfig_Null_VerifyCommand_Clears_On_Update()
    {
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, VerifyCommand = "dotnet test" });
        await _repo.SetConfigAsync(new ListConfigEntity { ListId = _listId, VerifyCommand = null });

        var fetched = await _repo.GetConfigAsync(_listId);
        Assert.NotNull(fetched);
        Assert.Null(fetched.VerifyCommand);
    }

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