import re
from typing import Any, Optional, Union, Dict, List
from .logger_config import get_logger

logger = get_logger(__name__)

# 预编译正则表达式
PATH_PATTERN = re.compile(r"\{([^}]+)\}")


def get_nested_value(
    data: Union[Dict, List, Any],
    path_str: str,
    default: Any = None,
    raise_error: bool = False,
) -> Any:
    """从嵌套字典或列表中根据路径字符串获取值

    支持以下格式的路径字符串：
    1. 简单路径: {res.data.token}
    2. 带前缀: Bearer {res.data.token}
    3. 带索引: {res.data.items[0].name}
    4. 带引号的键: {res.data."user.name"}

    Args:
        data: 要查询的数据，可以是字典、列表或其他类型
        path_str: 路径字符串，支持{prefix} {path}或{path}格式
        default: 当路径不存在时返回的默认值
        raise_error: 是否在出错时抛出异常，默认为False

    Returns:
        查询到的值或默认值

    Raises:
        ValueError: 当raise_error为True且路径格式无效时
        KeyError: 当raise_error为True且路径不存在时
        TypeError: 当raise_error为True且类型错误时
    """
    try:
        if not path_str:
            logger.warning("路径字符串为空")
            return default

        if data is None:
            logger.warning("输入数据为None")
            return default

        if not isinstance(data, (dict, list)):
            logger.warning(f"输入数据类型不支持: {type(data)}")
            return default

        # 使用预编译的正则表达式匹配路径
        matches = PATH_PATTERN.findall(path_str)

        if not matches:
            logger.warning(f"路径字符串格式无效: {path_str}")
            if raise_error:
                raise ValueError(f"路径字符串格式无效: {path_str}")
            return default

        # 处理路径
        if len(matches) == 1:
            actual_path = matches[0]
            # 获取{...}之前的所有文本作为前缀
            prefix = path_str[: path_str.find("{")].strip()
        elif len(matches) == 2:
            prefix = matches[0]
            actual_path = matches[1]
        else:
            logger.warning(f"路径字符串包含过多匹配项: {path_str}")
            if raise_error:
                raise ValueError(f"路径字符串包含过多匹配项: {path_str}")
            return default

        # 解析路径
        current = data
        # 使用更智能的路径分割
        path_parts = []
        current_part = ""
        in_quotes = False

        for char in actual_path:
            if char == '"':
                in_quotes = not in_quotes
                current_part += char
            elif char == "." and not in_quotes:
                path_parts.append(current_part)
                current_part = ""
            else:
                current_part += char

        if current_part:
            path_parts.append(current_part)

        for part in path_parts:
            # 处理数组索引
            if "[" in part and part.endswith("]"):
                key, index_str = part.split("[", 1)
                index_str = index_str.rstrip("]")

                # 获取键值
                if key and isinstance(current, dict):
                    current = current.get(key)
                elif not key and isinstance(current, list):
                    pass
                else:
                    logger.warning(f"无效的键: {key}")
                    if raise_error:
                        raise KeyError(f"无效的键: {key}")
                    return default

                # 获取索引
                try:
                    index = int(index_str)
                    if not isinstance(current, list) or not (0 <= index < len(current)):
                        logger.warning(f"无效的索引: {index}")
                        if raise_error:
                            raise IndexError(f"无效的索引: {index}")
                        return default
                    current = current[index]
                except ValueError:
                    logger.warning(f"无效的索引格式: {index_str}")
                    if raise_error:
                        raise ValueError(f"无效的索引格式: {index_str}")
                    return default
            else:
                # 处理普通键
                if isinstance(current, dict):
                    # 处理带引号的键
                    if part.startswith('"') and part.endswith('"'):
                        part = part[1:-1]
                    if part not in current:
                        logger.warning(f"键不存在: {part}")
                        if raise_error:
                            raise KeyError(f"键不存在: {part}")
                        return default
                    current = current[part]
                elif isinstance(current, list):
                    try:
                        index = int(part)
                        if not (0 <= index < len(current)):
                            logger.warning(f"索引越界: {index}")
                            if raise_error:
                                raise IndexError(f"索引越界: {index}")
                            return default
                        current = current[index]
                    except ValueError:
                        logger.warning(f"无效的列表索引: {part}")
                        if raise_error:
                            raise ValueError(f"无效的列表索引: {part}")
                        return default
                else:
                    logger.warning(f"无法访问键: {part}")
                    if raise_error:
                        raise TypeError(f"无法访问键: {part}")
                    return default

        # 处理前缀
        if prefix and current is not None:
            return f"{prefix} {current}"

        return current

    except Exception as e:
        logger.error(f"获取嵌套值失败: {str(e)}")
        if raise_error:
            raise
        return default
