using ClaudeDo.Worker.Git;

namespace ClaudeDo.Worker.Tests.Git;

public class WorktreeRootResolverTests
{
    [Fact]
    public void ResolveSiblingRoot_NoTrailingSeparator_ReturnsParent()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_no_sep");

        var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir);

        Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root);
    }

    [Fact]
    public void ResolveSiblingRoot_WithTrailingSeparator_StillReturnsParent()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_with_sep") + Path.DirectorySeparatorChar;

        var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir);

        Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root);
    }

    [Fact]
    public void ResolveSiblingRoot_WithTrailingAltSeparator_StillReturnsParent()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo_with_alt_sep") + "/";

        var root = WorktreeRootResolver.ResolveSiblingRoot(workingDir);

        Assert.Equal(Path.GetFullPath(Path.GetTempPath()).TrimEnd(Path.DirectorySeparatorChar), root);
    }

    [Fact]
    public void ResolveSiblingRoot_DriveRoot_Throws()
    {
        var driveRoot = Path.GetPathRoot(Path.GetTempPath())!;

        Assert.Throws<InvalidOperationException>(() => WorktreeRootResolver.ResolveSiblingRoot(driveRoot));
    }

    [Fact]
    public void EnsureOutsideWorkingDir_PathOutside_DoesNotThrow()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo");
        var worktreePath = Path.Combine(Path.GetTempPath(), ".claudedo-worktrees", "slug", "task1");

        WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir);
    }

    [Fact]
    public void EnsureOutsideWorkingDir_PathInsideWorkingDir_Throws()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo");
        var worktreePath = Path.Combine(workingDir, ".claudedo-worktrees", "slug", "task1");

        Assert.Throws<InvalidOperationException>(
            () => WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir));
    }

    [Fact]
    public void EnsureOutsideWorkingDir_PathEqualsWorkingDir_Throws()
    {
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo");

        Assert.Throws<InvalidOperationException>(
            () => WorktreeRootResolver.EnsureOutsideWorkingDir(workingDir, workingDir));
    }

    [Fact]
    public void EnsureOutsideWorkingDir_SiblingWithSharedPrefix_DoesNotThrow()
    {
        // "cd_repo-other" is NOT under "cd_repo" even though it shares a string prefix;
        // a naive StartsWith(workingDir) check would incorrectly reject this.
        var workingDir = Path.Combine(Path.GetTempPath(), "cd_repo");
        var worktreePath = Path.Combine(Path.GetTempPath(), "cd_repo-other", "task1");

        WorktreeRootResolver.EnsureOutsideWorkingDir(worktreePath, workingDir);
    }
}
