"""测试：PRISMA 流程计算 + SVG 生成（纯函数，不依赖 SA 模型）"""

from app.services.prisma_diagram import compute_prisma_flow, generate_prisma_svg, _prisma_labels


def _make_lit(stage_val: str, reason: str = ""):
    """用简单对象模拟 ReviewLiterature 的 stage/exclusion_reason 属性。"""
    return type("Lit", (), {"stage": stage_val, "exclusion_reason": reason})()


def _make_review():
    class Review:
        pass
    return Review()


def test_flow_empty_review():
    flow = compute_prisma_flow(_make_review(), [])
    assert flow["identification_total"] == 0
    assert flow["screened"] == 0
    assert flow["included_total"] == 0
    assert flow["excluded_reasons"] == {}


def test_flow_all_stages():
    """分布在各阶段的文献"""
    lits = [
        _make_lit("identification"),
        _make_lit("screening"),
        _make_lit("eligibility"),
        _make_lit("included"),
        _make_lit("excluded", "No full text;Wrong population"),
    ]
    flow = compute_prisma_flow(_make_review(), lits)
    assert flow["identification_total"] == 5
    assert flow["screened"] == 4  # identification 占 1
    assert flow["full_text_assessed"] == 3
    assert flow["included_total"] == 1
    assert flow["excluded_reasons"] == {"No full text": 1, "Wrong population": 1}


def test_flow_exclusion_reasons_split():
    """多个排除原因按分号拆分"""
    lits = [
        _make_lit("excluded", "No data;Wrong design"),
        _make_lit("excluded", "No data"),
        _make_lit("included"),
    ]
    flow = compute_prisma_flow(_make_review(), lits)
    assert flow["excluded_reasons"] == {"No data": 2, "Wrong design": 1}


def test_flow_exclusion_reasons_chinese_semicolon():
    """中文分号分隔也支持"""
    lits = [_make_lit("excluded", "无全文；非随机")]
    flow = compute_prisma_flow(_make_review(), lits)
    assert "无全文" in flow["excluded_reasons"]
    assert "非随机" in flow["excluded_reasons"]


def test_svg_output():
    flow = {
        "identification_total": 200,
        "duplicates_removed": 15,
        "screened": 185,
        "excluded_screening": 150,
        "full_text_assessed": 35,
        "excluded_eligibility": 25,
        "included_total": 10,
        "excluded_reasons": {"No data": 15, "Wrong design": 10},
    }
    svg = generate_prisma_svg(flow, "zh")
    assert svg.startswith("<?xml")
    assert "PRISMA 2020" in svg
    assert "200" in svg
    assert "150" in svg
    assert "10" in svg
    assert "No data (n=15)" in svg


def test_svg_english():
    flow = {"identification_total": 100, "screened": 80, "excluded_screening": 20,
            "full_text_assessed": 60, "excluded_eligibility": 40, "included_total": 20,
            "excluded_reasons": {}}
    svg = generate_prisma_svg(flow, "en")
    assert "PRISMA 2020 Flow Diagram" in svg


def test_svg_empty_excluded_reasons():
    flow = {"identification_total": 10, "screened": 8, "excluded_screening": 2,
            "full_text_assessed": 6, "excluded_eligibility": 4, "included_total": 2,
            "excluded_reasons": {}}
    svg = generate_prisma_svg(flow, "zh")
    assert "排除原因" in svg
    assert "Reasons for exclusion" not in svg  # 不应有英语标签


def test_prisma_labels_zh():
    labels = _prisma_labels("zh")
    assert labels["identification"] == "识别"
    assert labels["included"] == "纳入"


def test_prisma_labels_en():
    labels = _prisma_labels("en")
    assert labels["identification"] == "Identification"
    assert labels["included"] == "Included"
