"""שומר INV-EX4 — מקור-תבנית-יחיד לכל מפיקי-מסמכי-ההחלטה.

כל מפיק של מסמך-Word הקשור-להחלטה חייב להחיל עיצוב דרך הסגנונות שמוגדרים
בטמפלט היחיד (skills/docx/decision_template.docx), ולא לקבוע פונט/גודל ידנית
(``rFonts`` / ``sz`` / ``szCs``) — אלה נגזרים מ-styles.xml של הטמפלט.

הטסט גורף את מודולי-המפיקים ונכשל אם נבנה אלמנט ``w:rFonts`` / ``w:sz`` /
``w:szCs`` בקוד, אלא אם השורה נושאת את הסמן המפורש ``# INV-EX4-ok`` (חריג
מתועד — למשל חיזוק גופן-התבנית עצמו David כעקיפת באג-RTL של Word).

ספ: docs/spec/06-export.md §INV-EX4.
"""

from __future__ import annotations

import re
from pathlib import Path

import pytest

from legal_mcp.services import (
    analysis_docx_exporter,
    docx_exporter,
    docx_reviser,
    docx_retrofit,
)

# Every module that builds/edits a decision-related Word document.
_PRODUCER_MODULES = [
    docx_exporter,
    analysis_docx_exporter,
    docx_reviser,
    docx_retrofit,
]

# Construction (not lookup) of a hand-set font/size element:
#   OxmlElement("w:rFonts")          (python-docx producers)
#   etree.SubElement(rPr, _w("sz"))  (raw-lxml producer: docx_reviser)
_HANDSET_RE = re.compile(
    r'OxmlElement\(\s*["\']w:(?:rFonts|sz|szCs)["\']'
    r'|SubElement\([^)]*_w\(\s*["\'](?:rFonts|sz|szCs)["\']'
)

# Producers that build a document FROM SCRATCH must load the single template.
# (docx_reviser/docx_retrofit operate on an already-templated existing doc.)
_FROM_SCRATCH_MODULES = [docx_exporter, analysis_docx_exporter]


def _module_path(module) -> Path:
    return Path(module.__file__)


def test_no_handset_font_or_size_in_producers() -> None:
    """INV-EX4: no hand-set rFonts/sz/szCs in any producer (only via the
    template's named styles), unless explicitly marked ``# INV-EX4-ok``."""
    violations: list[str] = []
    for module in _PRODUCER_MODULES:
        path = _module_path(module)
        for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
            if _HANDSET_RE.search(line) and "INV-EX4-ok" not in line:
                violations.append(f"{path.name}:{lineno}: {line.strip()}")
    assert not violations, (
        "INV-EX4 violation — hand-set font/size outside the template styles "
        "(use a named template style, or mark with # INV-EX4-ok):\n  "
        + "\n  ".join(violations)
    )


@pytest.mark.parametrize("module", _FROM_SCRATCH_MODULES)
def test_from_scratch_producers_load_the_single_template(module) -> None:
    """INV-EX4: from-scratch producers reference the one template file."""
    source = _module_path(module).read_text(encoding="utf-8")
    assert "decision_template.docx" in source, (
        f"{_module_path(module).name} must load the single template "
        "skills/docx/decision_template.docx (INV-EX4)."
    )
