from __future__ import annotations

from typing import Any

COMPOSITE_RULE_TEMPLATE_KEY = "composite_rule_v1"

COMPOSITE_RULE_OPERATORS = {
    "exists_any",
    "exists_all",
    "all_present",
    "in_scope",
    "not_in_scope",
    "not_in_set",
    "overlap",
    "not_overlap",
    "date_outside_range",
    "numeric_compare",
    "duplicate_value",
    "contains_any",
    "not_contains_any",
}


def build_dsl_from_semantic_plan(semantic_plan: dict[str, Any]) -> dict[str, Any]:
    """把模型语义计划转换成可交给 validator 继续规范化的 DSL 草稿。"""

    if not isinstance(semantic_plan, dict):
        return {}
    text_parts = _semantic_text_parts(semantic_plan)
    field_keys = _semantic_field_keys(semantic_plan)
    if not text_parts and not field_keys:
        return {}
    return {
        "template_key": COMPOSITE_RULE_TEMPLATE_KEY,
        "field_keys": field_keys,
        "description": str(semantic_plan.get("rule_intent") or "").strip(),
        "condition_summary": "；".join(text_parts)[:800],
        "keywords": [],
        "rule_ir": {
            "facts": field_keys,
            "conditions": text_parts,
            "hit_logic": "由 DSL validator 根据字段本体和语义步骤生成受控条件",
        },
    }


def _semantic_text_parts(semantic_plan: dict[str, Any]) -> list[str]:
    parts: list[str] = []
    for key in ("rule_intent", "scope", "judgment_steps", "exception_conditions", "risk_action"):
        parts.extend(_flatten_semantic_text(semantic_plan.get(key)))
    return [item for index, item in enumerate(parts) if item and item not in parts[:index]]


def _semantic_field_keys(semantic_plan: dict[str, Any]) -> list[str]:
    keys: list[str] = []
    for value in (semantic_plan.get("required_fields"), semantic_plan.get("fields")):
        for item in value if isinstance(value, list) else []:
            key = item if isinstance(item, str) else next(
                (item.get(name) for name in ("field", "key", "field_key") if isinstance(item, dict) and item.get(name)),
                "",
            )
            text = str(key or "").strip()
            if "." in text and text not in keys:
                keys.append(text)
    return keys


def _flatten_semantic_text(value: Any) -> list[str]:
    if isinstance(value, str):
        return [value.strip()] if value.strip() else []
    if isinstance(value, list):
        return [item for value_item in value for item in _flatten_semantic_text(value_item)]
    if isinstance(value, dict):
        return [item for value_item in value.values() for item in _flatten_semantic_text(value_item)]
    return []
