from __future__ import annotations

from typing import Any, List, Sequence, Union


_路径类型 = Union[str, Sequence[Any]]


def _归一化路径(键路径: _路径类型, 分隔符: str) -> List[Any] | None:
    try:
        if isinstance(键路径, str):
            if 键路径 == "":
                return None
            return 键路径.split(分隔符)

        if isinstance(键路径, (list, tuple)):
            if len(键路径) == 0:
                return None
            return list(键路径)

        return None
    except Exception:
        return None


def 是否存在路径(
    数据: Any,
    键路径: _路径类型,
    分隔符: str = ".",
    键转字符串: bool = True,
) -> bool:
    """
    判断给定路径是否真实存在于嵌套结构中，支持 dict/list/tuple 混合结构。

    本函数用于补足“深层路径存在性判断”能力，
    与 `取值_路径` 的读取逻辑保持一致，但不会混淆“值为 None”与“路径不存在”。

    设计特性：
        - 支持字符串路径与路径序列；
        - 支持在 dict、list、tuple 混合结构中逐层判断；
        - 即使路径命中的最终值为 None，只要路径存在也返回 True；
        - 不对原始数据做任何修改；
        - 不抛出任何异常，适合作为条件判断类基础工具函数使用。

    行为说明：
        - 路径完整命中              → 返回 True；
        - 中途断路/越界/键不存在     → 返回 False；
        - 数据结构不支持继续遍历     → 返回 False。

    Args:
        数据 (Any): 任意输入对象，通常为 dict/list/tuple 的嵌套结构。
        键路径 (str | Sequence[Any]): 路径字符串或路径序列。
            - 字符串示例： "a.b.0.c"
            - 列表示例： ["a", "b", 0, "c"]
        分隔符 (str): 字符串路径的分隔符，默认 "."。
        键转字符串 (bool): 当走 dict 路径时，是否将键统一转为 str。默认 True。

    Returns:
        bool:
            True  - 路径存在；
            False - 路径不存在或数据非法。
    """
    try:
        路径列表 = _归一化路径(键路径, 分隔符)
        if not 路径列表:
            return False

        当前 = 数据

        for 段 in 路径列表:
            if isinstance(当前, dict):
                键名 = str(段) if 键转字符串 else 段
                if 键名 not in 当前:
                    return False
                当前 = 当前[键名]
                continue

            if isinstance(当前, (list, tuple)):
                try:
                    目标索引 = 段 if isinstance(段, int) else int(str(段))
                except Exception:
                    return False

                if 目标索引 < 0 or 目标索引 >= len(当前):
                    return False

                当前 = 当前[目标索引]
                continue

            return False

        return True
    except Exception:
        return False
