using ClaudeDo.Worker.Runner;

namespace ClaudeDo.Worker.Tests.Runner;

public class CommitMessageBuilderTests
{
    [Fact]
    public void Slug_FromListName()
    {
        Assert.Equal("lager-app", CommitMessageBuilder.ToSlug("Lager App"));
    }

    [Fact]
    public void Slug_SpecialCharsStripped()
    {
        Assert.Equal("my-list", CommitMessageBuilder.ToSlug("My! @List#"));
    }

    [Fact]
    public void Slug_CollapsesDashes()
    {
        Assert.Equal("a-b", CommitMessageBuilder.ToSlug("a   --  b"));
    }

    [Fact]
    public void Slug_TrimsLeadingTrailingDashes()
    {
        Assert.Equal("abc", CommitMessageBuilder.ToSlug("--abc--"));
    }

    [Fact]
    public void Title_TruncatedTo60()
    {
        var longTitle = new string('x', 80);
        var msg = CommitMessageBuilder.Build("feat", "My List", longTitle, null, "task-id-123");
        var header = msg.Split('\n')[0];
        // Header format: feat(my-list): <60 chars>
        var titlePart = header.Split(": ", 2)[1];
        Assert.Equal(60, titlePart.Length);
    }

    [Fact]
    public void NoDescription_TrailerStillPresent()
    {
        var msg = CommitMessageBuilder.Build("chore", "Test List", "do something", null, "abc-123");
        var lines = msg.Split('\n');

        // header \n \n trailer = 3 lines (no description block, just blank separator).
        Assert.Equal(3, lines.Length);
        Assert.Equal("chore(test-list): do something", lines[0]);
        Assert.Equal("", lines[1]);
        Assert.Equal("ClaudeDo-Task: abc-123", lines[2]);
    }

    [Fact]
    public void WithDescription_IncludedAboveTrailer()
    {
        var msg = CommitMessageBuilder.Build("feat", "Lager App", "add scan", "Detailed description here", "id-456");
        var lines = msg.Split('\n');

        Assert.Equal("feat(lager-app): add scan", lines[0]);
        Assert.Equal("", lines[1]); // blank after header
        Assert.Equal("Detailed description here", lines[2]);
        Assert.Equal("", lines[3]); // blank before trailer
        Assert.Equal("ClaudeDo-Task: id-456", lines[4]);
    }

    [Fact]
    public void BuildMerge_ConventionalHeaderWithMergeVerbAndTrailer()
    {
        var msg = CommitMessageBuilder.BuildMerge("fix", "Lager App", "stop the crash", "id-789");
        var lines = msg.Split('\n');

        Assert.Equal("fix(lager-app): merge stop the crash", lines[0]);
        Assert.Equal("", lines[1]);
        Assert.Equal("ClaudeDo-Task: id-789", lines[2]);
    }

    [Fact]
    public void BuildMerge_BlankCommitType_FallsBackToDefault()
    {
        var msg = CommitMessageBuilder.BuildMerge("  ", "My List", "do it", "id");
        Assert.StartsWith("chore(my-list): merge do it", msg);
    }

    [Fact]
    public void BuildMerge_ListNameWithoutSluggableChars_DropsScope()
    {
        var msg = CommitMessageBuilder.BuildMerge("feat", "!!!", "do it", "id");
        Assert.StartsWith("feat: merge do it", msg);
    }

    [Fact]
    public void BuildMerge_TitleTruncatedTo60()
    {
        var msg = CommitMessageBuilder.BuildMerge("feat", "My List", new string('x', 80), "id");
        var titlePart = msg.Split('\n')[0].Split(": merge ", 2)[1];
        Assert.Equal(60, titlePart.Length);
    }

    [Fact]
    public void Description_TruncatedTo400()
    {
        var longDesc = new string('d', 500);
        var msg = CommitMessageBuilder.Build("fix", "X", "title", longDesc, "id");
        var lines = msg.Split('\n');
        // lines[2] is the description line.
        Assert.Equal(400, lines[2].Length);
    }
}
