"""18+ 词条核实 — 词表命中 + 可选 LLM 分类。"""
from __future__ import annotations

import json
import re
from typing import Any

from niannian.llm.types import Message
from niannian.memory.adult_redaction import AdultRedactor

_VERIFY_SYSTEM = (
    "你是内容审核助手。判断给定中文词或短语是否属于露骨色情用语（18+ 成人向）。\n"
    "只输出一行 JSON，无其它文字："
    '{"adult": true或false, "confidence": 0到1的小数, "reason": "一句中文理由"}'
)

_JSON_RE = re.compile(r"\{[^{}]*\"adult\"[^{}]*\}", re.DOTALL)


def _parse_llm_verdict(raw: str) -> dict[str, Any] | None:
    text = (raw or "").strip()
    if not text:
        return None
    match = _JSON_RE.search(text)
    if not match:
        return None
    try:
        data = json.loads(match.group())
    except json.JSONDecodeError:
        return None
    if not isinstance(data, dict) or "adult" not in data:
        return None
    return {
        "adult": bool(data.get("adult")),
        "confidence": float(data.get("confidence") or 0.5),
        "reason": str(data.get("reason") or "").strip(),
    }


def verify_terms(
    terms: list[str],
    *,
    config: dict[str, Any],
    llm=None,
    use_llm: bool = True,
) -> list[dict[str, Any]]:
    """核实词条列表；已在词表者直接 adult=true，未知词可选 LLM。"""
    redactor = AdultRedactor.from_app_config(config)
    known = redactor.known_terms_set()
    out: list[dict[str, Any]] = []

    for raw in terms:
        term = str(raw or "").strip()
        if not term:
            continue
        if term in known:
            out.append(
                {
                    "term": term,
                    "adult": True,
                    "source": "lexicon",
                    "confidence": 1.0,
                    "reason": "已在 adult_terms 词表",
                }
            )
            continue

        if use_llm and llm is not None and llm.is_module_configured("brainstem"):
            messages = [
                Message(role="system", content=_VERIFY_SYSTEM),
                Message(role="user", content=f"词条：{term}"),
            ]
            try:
                reply = llm.complete("brainstem", messages, max_tokens=256, temperature=0.1)
                verdict = _parse_llm_verdict(reply.text)
            except Exception as exc:
                out.append(
                    {
                        "term": term,
                        "adult": None,
                        "source": "error",
                        "confidence": 0.0,
                        "reason": str(exc) or "LLM 核实失败",
                    }
                )
                continue
            if verdict is None:
                out.append(
                    {
                        "term": term,
                        "adult": None,
                        "source": "parse_error",
                        "confidence": 0.0,
                        "reason": "LLM 返回无法解析",
                    }
                )
                continue
            out.append(
                {
                    "term": term,
                    "adult": verdict["adult"],
                    "source": "llm",
                    "confidence": verdict["confidence"],
                    "reason": verdict["reason"],
                }
            )
            continue

        out.append(
            {
                "term": term,
                "adult": None,
                "source": "pending",
                "confidence": 0.0,
                "reason": "未在词表；需 use_llm=true 且 brainstem 已配置",
            }
        )
    return out
