using ClaudeDo.Worker.Runner;

namespace ClaudeDo.Worker.Tests.Runner;

public sealed class StreamAnalyzerTests
{
    [Fact]
    public void Extracts_Result_Markdown()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"result","result":"## Done","session_id":"sess-1"}""");
        var result = analyzer.GetResult();
        Assert.Equal("## Done", result.ResultMarkdown);
        Assert.Equal("sess-1", result.SessionId);
    }

    [Fact]
    public void Extracts_Structured_Output()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"result","result":"ok","structured_output":{"summary":"all good"},"session_id":"s1"}""");
        var result = analyzer.GetResult();
        Assert.Equal("ok", result.ResultMarkdown);
        Assert.Contains("all good", result.StructuredOutputJson);
    }

    [Fact]
    public void Counts_Assistant_Turns()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"assistant","message":"hi"}""");
        analyzer.ProcessLine("""{"type":"assistant","message":"working on it"}""");
        analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}""");
        var result = analyzer.GetResult();
        Assert.Equal(2, result.TurnCount);
    }

    [Fact]
    public void Accumulates_Token_Usage()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"stream_event","event":{"type":"message_start","message":{"usage":{"input_tokens":100,"output_tokens":50}}}}""");
        analyzer.ProcessLine("""{"type":"stream_event","event":{"type":"message_start","message":{"usage":{"input_tokens":200,"output_tokens":80}}}}""");
        analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}""");
        var result = analyzer.GetResult();
        Assert.Equal(300, result.TokensIn);
        Assert.Equal(130, result.TokensOut);
    }

    [Fact]
    public void Counts_Api_Retry_Events()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"system","subtype":"api_retry","attempt":1,"error":"rate_limit"}""");
        analyzer.ProcessLine("""{"type":"system","subtype":"api_retry","attempt":2,"error":"rate_limit"}""");
        analyzer.ProcessLine("""{"type":"result","result":"done","session_id":"s1"}""");
        var result = analyzer.GetResult();
        Assert.Equal(2, result.ApiRetryCount);
    }

    [Fact]
    public void Malformed_Json_Is_Ignored()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("not json {{{");
        analyzer.ProcessLine("");
        analyzer.ProcessLine("   ");
        var result = analyzer.GetResult();
        Assert.Null(result.ResultMarkdown);
        Assert.Equal(0, result.TurnCount);
    }

    [Fact]
    public void No_Result_Event_Returns_Null_Fields()
    {
        var analyzer = new StreamAnalyzer();
        analyzer.ProcessLine("""{"type":"assistant","message":"hi"}""");
        var result = analyzer.GetResult();
        Assert.Null(result.ResultMarkdown);
        Assert.Null(result.SessionId);
    }
}
