using ClaudeDo.Data.Git;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Config;
using ClaudeDo.Worker.Runner;
using ClaudeDo.Worker.Tests.Infrastructure;
using Microsoft.Extensions.Logging.Abstractions;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
using Xunit;

namespace ClaudeDo.Worker.Tests.Runner;

public sealed class ChildWorktreeBaseTests : IDisposable
{
    private readonly List<GitRepoFixture> _repos = new();
    private readonly List<DbFixture> _dbs = new();
    private readonly List<(string repoDir, string wtPath)> _cleanups = new();

    [Fact]
    public async Task ImprovementChild_basesOff_parentWorktreeHead()
    {
        if (!GitRepoFixture.IsGitAvailable()) { Assert.True(true, "git not available -- skipping"); return; }
        var repo = new GitRepoFixture(); _repos.Add(repo);
        var db = new DbFixture(); _dbs.Add(db);
        var listId = Guid.NewGuid().ToString();
        var parentId = Guid.NewGuid().ToString();
        var childId = Guid.NewGuid().ToString();
        var list = new ListEntity { Id = listId, Name = "L", WorkingDir = repo.RepoDir, CreatedAt = DateTime.UtcNow };
        var parent = new TaskEntity { Id = parentId, ListId = listId, Title = "Parent",
            CommitType = "chore", PlanningPhase = PlanningPhase.None, CreatedAt = DateTime.UtcNow };
        var child = new TaskEntity { Id = childId, ListId = listId, Title = "Improve",
            CommitType = "chore", ParentTaskId = parentId, CreatedBy = parentId, CreatedAt = DateTime.UtcNow };

        using (var seed = db.CreateContext())
        {
            await new ListRepository(seed).AddAsync(list);
            await new TaskRepository(seed).AddAsync(parent);
            await new TaskRepository(seed).AddAsync(child);
        }

        var cfg = new WorkerConfig { WorktreeRootStrategy = "sibling" };
        var mgr = new WorktreeManager(new GitService(), db.CreateFactory(), cfg, NullLogger<WorktreeManager>.Instance);

        var parentCtx = await mgr.CreateAsync(parent, list, CancellationToken.None);
        _cleanups.Add((repo.RepoDir, parentCtx.WorktreePath));
        File.WriteAllText(Path.Combine(parentCtx.WorktreePath, "parent.txt"), "parent work");
        await mgr.CommitIfChangedAsync(parentCtx, parent, list, CancellationToken.None);

        string parentHead;
        using (var read = db.CreateContext())
            parentHead = (await new WorktreeRepository(read).GetByTaskIdAsync(parentId))!.HeadCommit!;

        var childCtx = await mgr.CreateAsync(child, list, CancellationToken.None);
        _cleanups.Add((repo.RepoDir, childCtx.WorktreePath));

        Assert.Equal(parentHead, childCtx.BaseCommit);
        Assert.NotEqual(repo.BaseCommit, childCtx.BaseCommit);
        Assert.True(File.Exists(Path.Combine(childCtx.WorktreePath, "parent.txt")));
    }

    public void Dispose()
    {
        foreach (var (repoDir, wtPath) in _cleanups)
            try { GitRepoFixture.RunGit(repoDir, "worktree", "remove", "--force", wtPath); } catch { }
        foreach (var r in _repos) r.Dispose();
        foreach (var d in _dbs) d.Dispose();
    }
}
