using ClaudeDo.Worker.Agents;

namespace ClaudeDo.Worker.Tests.Services;

public sealed class DefaultAgentSeederTests : IDisposable
{
    private readonly string _bundleDir;
    private readonly string _targetDir;

    public DefaultAgentSeederTests()
    {
        var root = Path.Combine(Path.GetTempPath(), $"claudedo_seeder_{Guid.NewGuid():N}");
        _bundleDir = Path.Combine(root, "bundle");
        _targetDir = Path.Combine(root, "target");
        Directory.CreateDirectory(_bundleDir);
        Directory.CreateDirectory(_targetDir);
    }

    public void Dispose()
    {
        try { Directory.Delete(Path.GetDirectoryName(_bundleDir)!, true); } catch { }
    }

    private async Task WriteBundleAsync(string name, string content)
    {
        await File.WriteAllTextAsync(Path.Combine(_bundleDir, name), content);
    }

    [Fact]
    public async Task SeedMissing_CopiesAllFiles_WhenTargetEmpty()
    {
        await WriteBundleAsync("a.md", "A");
        await WriteBundleAsync("b.md", "B");
        var seeder = new DefaultAgentSeeder(_bundleDir, _targetDir);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(2, result.Copied);
        Assert.Equal(0, result.Skipped);
        Assert.True(File.Exists(Path.Combine(_targetDir, "a.md")));
        Assert.True(File.Exists(Path.Combine(_targetDir, "b.md")));
    }

    [Fact]
    public async Task SeedMissing_SkipsExistingFiles()
    {
        await WriteBundleAsync("a.md", "bundled");
        await File.WriteAllTextAsync(Path.Combine(_targetDir, "a.md"), "user-modified");
        var seeder = new DefaultAgentSeeder(_bundleDir, _targetDir);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(0, result.Copied);
        Assert.Equal(1, result.Skipped);
        var content = await File.ReadAllTextAsync(Path.Combine(_targetDir, "a.md"));
        Assert.Equal("user-modified", content);
    }

    [Fact]
    public async Task SeedMissing_MixedState_CopiesOnlyMissing()
    {
        await WriteBundleAsync("a.md", "A");
        await WriteBundleAsync("b.md", "B");
        await File.WriteAllTextAsync(Path.Combine(_targetDir, "a.md"), "existing");
        var seeder = new DefaultAgentSeeder(_bundleDir, _targetDir);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(1, result.Copied);
        Assert.Equal(1, result.Skipped);
        Assert.Equal("existing", await File.ReadAllTextAsync(Path.Combine(_targetDir, "a.md")));
        Assert.Equal("B", await File.ReadAllTextAsync(Path.Combine(_targetDir, "b.md")));
    }

    [Fact]
    public async Task SeedMissing_ReturnsZero_WhenBundleDirMissing()
    {
        var missingBundle = Path.Combine(Path.GetTempPath(), $"claudedo_missing_{Guid.NewGuid():N}");
        var seeder = new DefaultAgentSeeder(missingBundle, _targetDir);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(0, result.Copied);
        Assert.Equal(0, result.Skipped);
    }

    [Fact]
    public async Task SeedMissing_CreatesTargetDir_IfMissing()
    {
        await WriteBundleAsync("a.md", "A");
        var missingTarget = Path.Combine(_targetDir, "nested", "created");
        var seeder = new DefaultAgentSeeder(_bundleDir, missingTarget);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(1, result.Copied);
        Assert.True(File.Exists(Path.Combine(missingTarget, "a.md")));
    }

    [Fact]
    public async Task SeedMissing_IgnoresNonMarkdownFiles()
    {
        await WriteBundleAsync("a.md", "A");
        await File.WriteAllTextAsync(Path.Combine(_bundleDir, "readme.txt"), "not an agent");
        var seeder = new DefaultAgentSeeder(_bundleDir, _targetDir);

        var result = await seeder.SeedMissingAsync();

        Assert.Equal(1, result.Copied);
        Assert.False(File.Exists(Path.Combine(_targetDir, "readme.txt")));
    }
}
