"""标点符号专项规则。"""

import re
from fastapi_modules.fastapi_leaudit.govdoc_engine.engine.checks import register
from fastapi_modules.fastapi_leaudit.govdoc_engine.engine.checks.base import CheckBase, CheckContext, CheckHit, CheckResult


# 多书名号或引号并列时不应用顿号分隔（中文/中文标点）
_QUOTE_DUNHAO_RE = re.compile(r"([”》])、([“《])")
# 句内括号末尾（除问号/叹号/省略号外）不应有标点
_PAREN_PUNCT_RE = re.compile(r"[（(][^）)]*?[，。；：、][）)]")
# 引号嵌套：双引号内含单引号包裹的强调短语（如 "卓'粤'创一流"）
_NESTED_QUOTE_RE = re.compile(r"“[^“”]*?‘[^‘’]+’[^“”]*?”")


@register("punctuation")
class PunctuationCheck(CheckBase):
    def run(self, ctx: CheckContext) -> CheckResult:
        rules = ctx.stage.rules or []
        hits: list[CheckHit] = []
        for p in ctx.paragraphs:
            for r in rules:
                t = r.get("type")
                if t == "no_dunhao_between_quotes":
                    for m in _QUOTE_DUNHAO_RE.finditer(p.text):
                        hits.append(CheckHit(
                            paragraph=p, char_start=m.start(), char_end=m.end(),
                            actual={"text": m.group(0)},
                            expected={"text": m.group(0).replace("、", "")},
                            message="多个引号/书名号并列不应用顿号分隔",
                        ))
                elif t == "no_punct_inside_inline_paren":
                    for m in _PAREN_PUNCT_RE.finditer(p.text):
                        hits.append(CheckHit(
                            paragraph=p, char_start=m.start(), char_end=m.end(),
                            actual={"text": m.group(0)},
                            message="句内括号末尾通常不应含标点",
                        ))
                elif t == "no_outer_quote_when_inner_quote":
                    for m in _NESTED_QUOTE_RE.finditer(p.text):
                        hits.append(CheckHit(
                            paragraph=p, char_start=m.start(), char_end=m.end(),
                            actual={"text": m.group(0)},
                            message="双引号内已含单引号强调时，外层不应再加双引号",
                        ))
        return CheckResult(passed=not hits, hits=hits)
