import copy
import json
import re
import sys
from typing import Any


CN_NUM = "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u3007\u96f6\u4e24"

CHAPTER_PATTERN = re.compile(rf"^\s*\u7b2c\s*([{CN_NUM}\d]+)\s*\u7ae0")
CN_LEVEL1_PATTERN = re.compile(rf"^\s*([{CN_NUM}]+)(?=\s|[\u3001\u3002\uff0e.])")

CASE_LIKE_PATTERN = re.compile(r"^\s*\d+(?:\.|\uff0e)(?!\d|\s|$)")
ARABIC_PATTERN = re.compile(
    r"^\s*(\d+(?:\.\d+)*)(?=\s|[\u4e00-\u9fff\u3001\u3002\uff0e]|$|\.(?:\s|$))"
)


def has_valid_text_level(item: dict) -> bool:
    return "text_level" in item and item.get("text_level") not in (None, "")


def parse_heading(text: str):
    text = text.strip()
    if not text:
        return None, None

    if CASE_LIKE_PATTERN.match(text):
        return "case_like", None

    if CHAPTER_PATTERN.match(text):
        return "level1", None

    if CN_LEVEL1_PATTERN.match(text):
        return "level1", None

    match = ARABIC_PATTERN.match(text)
    if match:
        return "arabic", match.group(1)

    return None, None


def arabic_depth(number: str) -> int:
    return number.count(".") + 1


def parent_number(number: str) -> str | None:
    parts = number.split(".")
    if len(parts) <= 1:
        return None
    return ".".join(parts[:-1])


def collect_headings(data: list) -> list:
    headings = []

    for item in data:
        if not isinstance(item, dict):
            continue
        if item.get("type") != "text":
            continue
        if not has_valid_text_level(item):
            continue

        kind, number = parse_heading(item.get("text", ""))
        if kind in {"level1", "arabic", "case_like"}:
            headings.append({"kind": kind, "number": number})

    return headings


def is_valid_arabic_hierarchy(numbers: list[str], allow_missing_depth1_parent: bool) -> bool:
    seen = set()
    has_depth2 = False
    has_depth3 = False

    for number in numbers:
        depth = arabic_depth(number)
        if depth >= 2:
            has_depth2 = True
        if depth >= 3:
            has_depth3 = True

        parent = parent_number(number)
        if parent is not None:
            parent_depth = arabic_depth(parent)
            parent_is_missing_depth1 = allow_missing_depth1_parent and parent_depth == 1
            if parent not in seen and not parent_is_missing_depth1:
                return False

        seen.add(number)

    return has_depth2 and has_depth3


def detect_valid_mode(headings: list):
    if not headings:
        return None

    if any(heading["kind"] == "case_like" for heading in headings):
        return None

    first = headings[0]

    if first["kind"] == "arabic":
        numbers = [heading["number"] for heading in headings if heading["kind"] == "arabic"]
        if numbers and arabic_depth(numbers[0]) == 1:
            if is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=False):
                return "A"
        return None

    if first["kind"] == "level1":
        numbers = [heading["number"] for heading in headings[1:] if heading["kind"] == "arabic"]
        if not numbers:
            return None

        first_depth = arabic_depth(numbers[0])
        if first_depth == 2 and is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=True):
            return "B"

        if first_depth == 1 and is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=False):
            return "C"

    return None


JsonContent = Any


def reset_textlevel(json_content: JsonContent) -> JsonContent:
    """
    输入 JSON 内容，返回更新 text_level 后的新 JSON 内容。

    json_content 可以是已经 json.load/json.loads 后的 Python 对象，
    也可以是 JSON 字符串。函数不会修改原始入参。
    """
    if isinstance(json_content, str):
        data = json.loads(json_content)
    else:
        data = copy.deepcopy(json_content)

    if not isinstance(data, list):
        return data

    headings = collect_headings(data)
    mode = detect_valid_mode(headings)

    if mode is None:
        return data

    for item in data:
        if not isinstance(item, dict):
            continue
        if item.get("type") != "text":
            continue
        if not has_valid_text_level(item):
            continue

        kind, number = parse_heading(item.get("text", ""))
        if kind == "level1":
            item["text_level"] = 1
            continue
        if kind != "arabic":
            continue

        depth = arabic_depth(number)
        item["text_level"] = depth if mode in {"A", "B"} else depth + 1

    return data





if __name__ == "__main__":
    json_file_path = r'E:\ZKYNLP\Hjunproject\project0506\kgrag\163-06A0014-B01001_发动机-维修手册_content_list.json'
    with open(json_file_path, "r", encoding="utf-8") as f:
        json_content = json.load(f)
    result=  reset_textlevel(json_content)

    for ins in result[:30]:
        print(ins)
    # print(json.dumps(result, ensure_ascii=False, indent=2))
