"""Schema Flattener - 将定义树预处理为 LLM 友好的格式.

将嵌套的定义 JSON 转换为三种格式：
1. tree_view: 可视化树形文本，帮助 LLM 理解层级关系
2. output_template: JSON 骨架模板，明确输出结构
3. property_paths: 扁平化属性列表，用于分步提取
"""

from __future__ import annotations

import json
from typing import Any

DefinitionNode = dict[str, Any]


# ── 公共接口 ──────────────────────────────────────────────────────────────────

def flatten_to_tree_view(definition: DefinitionNode) -> str:
    """将定义树转换为可视化树形文本.

    示例输出::

        PDJH (派对计划) [concept]
        ├── JBXX (基本信息) [concept]
        │   ├── PDMC (派对名称) [string, 单值]
        │   └── SFBA (是否备案) [boolean, 单值]
        └── RYXX (人员信息) [concept]
            └── RYQD (人员清单) [class, 列表]
                ├── XM (姓名) [string, 单值]
                └── XB (性别) [string, 单值]
    """
    lines: list[str] = []
    _build_tree_recursive(definition, lines, is_root=True)
    return "\n".join(lines)


def generate_output_template(definition: DefinitionNode) -> dict[str, Any]:
    """根据定义生成 JSON 骨架模板，作为 LLM 输出的参考结构.

    规则:
    - concept → {}
    - property (class, is_list=false) → {子属性}
    - property (class, is_list=true) → [{子属性}]
    - property (基础类型, is_list=false) → 类型占位值
    - property (基础类型, is_list=true) → [类型占位值]
    """
    return _build_template_recursive(definition)


def get_property_paths(definition: DefinitionNode) -> list[dict[str, Any]]:
    """获取所有叶子属性的扁平列表（仅基础类型，不含 class 和 concept）.

    返回::

        [
            {"path": "PDJH.JBXX.PDMC", "name": "派对名称", "value_type": "string", "is_list": False},
            ...
        ]
    """
    result: list[dict[str, Any]] = []
    _collect_leaf_properties(definition, prefix="", result=result)
    return result


def get_structured_property_list(definition: DefinitionNode) -> str:
    """生成带类型标注的结构化属性列表，供 LLM 理解每个字段的含义和类型.

    输出示例::

        PDJH (派对计划)
          JBXX (基本信息)
            PDMC (派对名称) → string, 单值
            PDKSSJ (派对开始时间) → date_time, 单值
          RYXX (人员信息)
            ZCH (总策划) → class, 单值
              XM (姓名) → string, 单值
              XB (性别) → string, 单值
            RYQD (人员清单) → class, 列表
              XM (姓名) → string, 单值
              XB (性别) → string, 单值
    """
    lines: list[str] = []
    _build_property_list_recursive(definition, lines, indent=0)
    return "\n".join(lines)


# ── 内部实现 ──────────────────────────────────────────────────────────────────

def _build_tree_recursive(
    node: DefinitionNode,
    lines: list[str],
    is_root: bool = False,
    prefix: str = "",
    is_last: bool = True,
) -> None:
    metadata = node["metadata"]
    label = metadata["node_label"]
    name = metadata["node_name"]
    node_type = metadata["node_type"]

    # 构建类型标注
    if node_type == "concept":
        type_info = "[concept]"
    else:
        value_type = metadata["value_type"]
        multiplicity = "列表" if metadata.get("is_list", False) else "单值"
        type_info = f"[{value_type}, {multiplicity}]"

    # 构建前缀和连接符
    if is_root:
        lines.append(f"{label} ({name}) {type_info}")
    else:
        connector = "└── " if is_last else "├── "
        lines.append(f"{prefix}{connector}{label} ({name}) {type_info}")

    # 递归处理子节点
    subnodes = node.get("subnodes", {})
    if not subnodes:
        return

    keys = list(subnodes.keys())
    for i, key in enumerate(keys):
        child_is_last = i == len(keys) - 1
        if is_root:
            child_prefix = ""
        else:
            extension = "    " if is_last else "│   "
            child_prefix = prefix + extension

        _build_tree_recursive(
            subnodes[key],
            lines,
            is_root=False,
            prefix=child_prefix,
            is_last=child_is_last,
        )


def _build_template_recursive(node: DefinitionNode) -> Any:
    metadata = node["metadata"]
    node_type = metadata["node_type"]

    if node_type == "concept":
        result: dict[str, Any] = {}
        for key, subnode in node.get("subnodes", {}).items():
            result[key] = _build_template_recursive(subnode)
        return result

    # node_type == "property"
    value_type = metadata["value_type"]
    is_list = metadata.get("is_list", False)

    if value_type == "class":
        sub_template: dict[str, Any] = {}
        for key, subnode in node.get("subnodes", {}).items():
            sub_template[key] = _build_template_recursive(subnode)
        return [sub_template] if is_list else sub_template

    placeholder = _get_placeholder(value_type)
    return [placeholder] if is_list else placeholder


_PLACEHOLDERS: dict[str, Any] = {
    "integer": 0,
    "float": 0.0,
    "string": "",
    "boolean": False,
    "date_time": "YYYY-MM-DDTHH:mm:ss.SSS",
}


def _get_placeholder(value_type: str) -> Any:
    return _PLACEHOLDERS.get(value_type)


def _collect_leaf_properties(
    node: DefinitionNode,
    prefix: str,
    result: list[dict[str, Any]],
) -> None:
    metadata = node["metadata"]
    label = metadata["node_label"]
    current_path = f"{prefix}.{label}" if prefix else label

    if metadata["node_type"] == "concept":
        for key, subnode in node.get("subnodes", {}).items():
            _collect_leaf_properties(subnode, current_path, result)
    elif metadata["value_type"] == "class":
        for key, subnode in node.get("subnodes", {}).items():
            _collect_leaf_properties(subnode, current_path, result)
    else:
        result.append({
            "path": current_path,
            "label": label,
            "name": metadata["node_name"],
            "value_type": metadata["value_type"],
            "is_list": metadata.get("is_list", False),
        })


def _build_property_list_recursive(
    node: DefinitionNode,
    lines: list[str],
    indent: int,
) -> None:
    metadata = node["metadata"]
    label = metadata["node_label"]
    name = metadata["node_name"]
    pad = "  " * indent

    if metadata["node_type"] == "concept":
        lines.append(f"{pad}{label} ({name})")
        for key, subnode in node.get("subnodes", {}).items():
            _build_property_list_recursive(subnode, lines, indent + 1)
    else:
        value_type = metadata["value_type"]
        is_list = metadata.get("is_list", False)
        mult = "列表" if is_list else "单值"
        lines.append(f"{pad}{label} ({name}) → {value_type}, {mult}")
        if value_type == "class":
            for key, subnode in node.get("subnodes", {}).items():
                _build_property_list_recursive(subnode, lines, indent + 1)


# ── 调试用 ────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    import pathlib

    sample = json.loads(
        pathlib.Path("data/samples/info_definition.json").read_text(encoding="utf-8")
    )

    print("=== Tree View ===")
    print(flatten_to_tree_view(sample))
    print()

    print("=== Output Template ===")
    print(json.dumps(generate_output_template(sample), ensure_ascii=False, indent=2))
    print()

    print("=== Property Paths ===")
    for p in get_property_paths(sample):
        print(f"  {p['path']} ({p['name']}): {p['value_type']}, list={p['is_list']}")
