"""JSON 提取工具函数

从可能包含 markdown 代码块或周围文本的 LLM 响应中提取 JSON 字符串。
采用深度计数器方式确保正确匹配嵌套括号。
"""
import json
import re


def extract_json(text: str) -> str:
    """从文本中提取 JSON 字符串。

    提取策略（按优先级）：
    1. 尝试直接解析整个文本为 JSON
    2. 尝试从 ```json ... ``` 代码块中提取
    3. 使用深度计数器找到第一个完整的 JSON 对象或数组

    Args:
        text: 可能包含 JSON 的文本

    Returns:
        提取出的 JSON 字符串

    Raises:
        ValueError: 无法从文本中提取有效 JSON
    """
    if not text or not text.strip():
        raise ValueError(f"无法从响应中提取JSON: {text[:200]}")

    # 1. 尝试直接解析
    try:
        json.loads(text)
        return text
    except json.JSONDecodeError:
        pass

    # 2. 尝试从代码块中提取
    match = re.search(r"```(?:json)?\s*\n?(.*?)\n?```", text, re.DOTALL)
    if match:
        candidate = match.group(1).strip()
        try:
            json.loads(candidate)
            return candidate
        except json.JSONDecodeError:
            pass

    # 3. 使用深度计数器找到第一个完整的 JSON 对象或数组
    for i, c in enumerate(text):
        if c in "[{":
            depth = 0
            for j in range(i, len(text)):
                if text[j] in "[{":
                    depth += 1
                elif text[j] in "]}":
                    depth -= 1
                if depth == 0:
                    candidate = text[i : j + 1]
                    try:
                        json.loads(candidate)
                        return candidate
                    except json.JSONDecodeError:
                        break  # 这对括号不是有效 JSON，继续找下一对
            # 如果 depth != 0 说明括号不匹配，继续找下一个起始括号

    raise ValueError(f"无法从响应中提取JSON: {text[:200]}")
