using ClaudeDo.Ui.Helpers;

namespace ClaudeDo.Ui.Tests.Helpers;

public class StreamLineFormatterTests
{
    private readonly StreamLineFormatter _formatter = new();

    // --- Text deltas ---

    [Fact]
    public void FormatLine_TextDelta_ReturnsTextContent()
    {
        var line = """{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello world"}}}""";
        Assert.Equal("Hello world", _formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_ConsecutiveTextDeltas_ReturnEachDelta()
    {
        var line1 = """{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello "}}}""";
        var line2 = """{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"world"}}}""";
        Assert.Equal("Hello ", _formatter.FormatLine(line1));
        Assert.Equal("world", _formatter.FormatLine(line2));
    }

    [Fact]
    public void FormatLine_ContentBlockStop_ReturnsNewline()
    {
        var line = """{"type":"stream_event","event":{"type":"content_block_stop","index":0}}""";
        Assert.Equal("\n", _formatter.FormatLine(line));
    }

    // --- Tool use, result, system, fallback ---

    [Fact]
    public void FormatLine_ToolUseStart_ReturnsToolNameLine()
    {
        var line = """{"type":"stream_event","event":{"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"x","name":"bash"}}}""";
        Assert.Equal("\n[Tool: bash]\n", _formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_InputJsonDelta_ReturnsNull()
    {
        var line = """{"type":"stream_event","event":{"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"cmd\":"}}}""";
        Assert.Null(_formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_Result_ReturnsFormattedResult()
    {
        var line = """{"type":"result","result":"Done."}""";
        Assert.Equal("\n--- Result ---\nDone.\n", _formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_ApiRetry_ReturnsRetryNotice()
    {
        var line = """{"type":"system","subtype":"api_retry"}""";
        Assert.Equal("\n[Retrying API call...]\n", _formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_SystemNonRetry_ReturnsNull()
    {
        var line = """{"type":"system","subtype":"init"}""";
        Assert.Null(_formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_AssistantType_ReturnsNull()
    {
        var line = """{"type":"assistant","message":{}}""";
        Assert.Null(_formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_MalformedJson_ReturnsRawLine()
    {
        var line = "not json at all";
        Assert.Equal("not json at all", _formatter.FormatLine(line));
    }

    [Fact]
    public void FormatLine_MessageStartAndDelta_ReturnsNull()
    {
        var start = """{"type":"stream_event","event":{"type":"message_start","message":{}}}""";
        var delta = """{"type":"stream_event","event":{"type":"message_delta","delta":{}}}""";
        Assert.Null(_formatter.FormatLine(start));
        Assert.Null(_formatter.FormatLine(delta));
    }

    // --- FormatFile and Trim ---

    [Fact]
    public void FormatFile_ParsesAllLinesAndReturnsFormattedText()
    {
        var lines = new[]
        {
            """{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}}""",
            """{"type":"stream_event","event":{"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"x","name":"bash"}}}""",
            """{"type":"result","result":"Done."}""",
        };
        var file = Path.GetTempFileName();
        try
        {
            File.WriteAllLines(file, lines);
            var result = _formatter.FormatFile(file);
            Assert.Contains("Hello", result);
            Assert.Contains("[Tool: bash]", result);
            Assert.Contains("Done.", result);
        }
        finally
        {
            File.Delete(file);
        }
    }

    [Fact]
    public void FormatFile_TrimsLargeContent()
    {
        var chunk = new string('x', 1000);
        var line = "{\"type\":\"stream_event\",\"event\":{\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"" + chunk + "\"}}}";
        var lines = Enumerable.Repeat(line, 65).ToArray();
        var file = Path.GetTempFileName();
        try
        {
            File.WriteAllLines(file, lines);
            var result = _formatter.FormatFile(file);
            Assert.True(result.Length <= 50_200, $"Expected <= 50200 but got {result.Length}");
        }
        finally
        {
            File.Delete(file);
        }
    }
}
