from pathlib import Path

from docx import Document

from app.review_filler import (
    build_review_decisions,
    extract_review_tables,
    fill_review_docx_from_analysis,
    parse_analysis_markdown,
    select_review_table,
    validate_review_results,
)


ROOT_DIR = Path(__file__).resolve().parent.parent
ANALYSIS_MD = ROOT_DIR / "test" / "中央处理机正常模式软件任务书V1_00_094006f6_analysis.md"
REVIEW_DOCX = ROOT_DIR / "test" / "附录A文档审查.docx"


def test_parse_analysis_markdown_extracts_evidence_sections() -> None:
    analysis = parse_analysis_markdown(ANALYSIS_MD)
    sections = {item.section for item in analysis.evidences}
    polarities = {item.polarity for item in analysis.evidences}

    assert analysis.source_filename == "中央处理机正常模式软件任务书V1.00.docx"
    assert "符合项" in sections
    assert "不符合项" in sections
    assert "缺失章节或缺失证据" in sections
    assert {"positive", "negative", "manual"}.issubset(polarities)
    assert any("合格性规定" in item.text for item in analysis.evidences)


def test_extract_review_tables_skips_qitao_and_selects_a2_for_requirements_analysis() -> None:
    analysis = parse_analysis_markdown(ANALYSIS_MD)
    tables = extract_review_tables(REVIEW_DOCX)
    selected = select_review_table(analysis, tables)

    assert [table.heading for table in tables] == [
        "A.2软件需求规格说明审查单",
        "A.3软件设计文档审查单",
        "A.4用户手册审查单",
    ]
    assert selected.heading == "A.2软件需求规格说明审查单"
    assert len(selected.criteria) == 24
    assert selected.criteria[0].sequence == "1"
    assert selected.criteria[0].category == "完整性"


def test_build_review_decisions_uses_negative_evidence_for_missing_sections() -> None:
    analysis = parse_analysis_markdown(ANALYSIS_MD)
    table = select_review_table(analysis, extract_review_tables(REVIEW_DOCX))
    decisions = build_review_decisions(analysis, table)

    assert len(decisions) == 24
    assert {decision.result for decision in decisions}.issubset({"通过", "未通过", "不适用"})
    assert decisions[0].criterion.sequence == "1"
    assert decisions[0].result == "未通过"
    assert any("缩略名" in evidence.text or "版本号" in evidence.text for evidence in decisions[0].evidence)

    missing_qualification = [
        decision
        for decision in decisions
        if "合格性规定" in decision.criterion.content or "合格性" in decision.reason
    ]
    assert missing_qualification
    assert all(decision.result == "未通过" for decision in missing_qualification)


def test_fill_review_docx_from_analysis_writes_mutually_exclusive_results(tmp_path: Path) -> None:
    output_docx = tmp_path / "review-filled.docx"
    result = fill_review_docx_from_analysis(ANALYSIS_MD, REVIEW_DOCX, output_docx)

    assert result.target_heading == "A.2软件需求规格说明审查单; A.3软件设计文档审查单; A.4用户手册审查单"
    assert len(result.decisions) == 70
    assert output_docx.exists()
    assert validate_review_results(output_docx, "A.2") == []
    assert validate_review_results(output_docx, "A.3") == []
    assert validate_review_results(output_docx, "A.4") == []

    document = Document(output_docx)
    expected_rows = {1: 24, 2: 18, 3: 28}
    for table_index, expected_count in expected_rows.items():
        marked_rows = 0
        for row in document.tables[table_index].rows[3:]:
            sequence = row.cells[0].text.strip()
            if not sequence.isdigit():
                continue
            marks = [row.cells[index].text.strip() for index in (3, 4, 5)]
            assert sum(1 for value in marks if value == "✔") == 1
            marked_rows += 1
        assert marked_rows == expected_count
