package tech.easyflow.core.runtime;

import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * {@link LegacyThinkingTagParser} 流式兼容测试。
 */
public class LegacyThinkingTagParserTest {

    /**
     * 验证跨增量拆分的开始与结束标签可以正确解析。
     */
    @Test
    public void shouldSplitThinkingTagsAcrossChunks() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptContent("  <thi"));
        segments.addAll(parser.acceptContent("nk>先分析</thi"));
        segments.addAll(parser.acceptContent("nk>\n最终回答"));
        segments.addAll(parser.finish());

        Assert.assertTrue(parser.isLegacyFormatDetected());
        Assert.assertEquals("先分析", join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
        Assert.assertEquals("\n最终回答", join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
    }

    /**
     * 验证 {@code <thinking>} 别名及其跨增量结束标签可以正确解析。
     */
    @Test
    public void shouldSplitThinkingAliasAcrossChunks() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptContent("<thinking>先分析</think"));
        segments.addAll(parser.acceptContent("ing>最终回答"));
        segments.addAll(parser.finish());

        Assert.assertTrue(parser.isLegacyFormatDetected());
        Assert.assertEquals("先分析", join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
        Assert.assertEquals("最终回答", join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
    }

    /**
     * 验证普通正文中的标签示例不会被错误拆分。
     */
    @Test
    public void shouldKeepThinkTagWhenItIsNotAtResponseStart() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptContent("示例：<think>内容</think>"));
        segments.addAll(parser.finish());

        Assert.assertFalse(parser.isLegacyFormatDetected());
        Assert.assertEquals("示例：<think>内容</think>",
                join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
        Assert.assertEquals("", join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
    }

    /**
     * 验证结构化思考协议会旁路旧标签识别。
     */
    @Test
    public void shouldBypassLegacyParsingForStructuredReasoning() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptReasoning("结构化思考"));
        segments.addAll(parser.acceptContent("<think>正文标签示例</think>"));

        Assert.assertFalse(parser.isLegacyFormatDetected());
        Assert.assertEquals("结构化思考", join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
        Assert.assertEquals("<think>正文标签示例</think>",
                join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
    }

    /**
     * 验证空结构化思考不会阻止正文开头的旧标签识别。
     */
    @Test
    public void shouldParseLegacyTagWhenStructuredReasoningIsBlank() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptReasoning("  "));
        segments.addAll(parser.acceptContent("<think>旧版思考</think>正文"));

        Assert.assertTrue(parser.isLegacyFormatDetected());
        Assert.assertEquals("旧版思考", join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
        Assert.assertEquals("正文", join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
    }

    /**
     * 验证未闭合的旧思考标签在流结束时仍作为思考内容收口。
     */
    @Test
    public void shouldFlushUnclosedThinkingAsReasoning() {
        LegacyThinkingTagParser parser = new LegacyThinkingTagParser();
        List<LegacyThinkingTagParser.Segment> segments = new ArrayList<>();

        segments.addAll(parser.acceptContent("<think>尚未完成</thi"));
        segments.addAll(parser.finish());

        Assert.assertTrue(parser.isLegacyFormatDetected());
        Assert.assertEquals("尚未完成</thi",
                join(segments, LegacyThinkingTagParser.SegmentType.REASONING));
        Assert.assertEquals("", join(segments, LegacyThinkingTagParser.SegmentType.CONTENT));
    }

    private String join(List<LegacyThinkingTagParser.Segment> segments,
                        LegacyThinkingTagParser.SegmentType type) {
        return segments.stream()
                .filter(segment -> segment.getType() == type)
                .map(LegacyThinkingTagParser.Segment::getText)
                .reduce("", String::concat);
    }
}
