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) -> bool:
    try:
        if isinstance(路径段, bool):
            return False

        索引 = 路径段 if isinstance(路径段, int) else int(str(路径段))
        return 索引 >= 0
    except Exception:
        return False


def 确保路径存在(
    数据: Any,
    键路径: _路径类型,
    分隔符: str = ".",
    键转字符串: bool = True,
) -> bool:
    """
    确保给定路径在嵌套结构中存在，不存在时自动补齐空字典或空列表。

    本函数用于为后续写入或深层访问预先铺好结构，
    与 `取值_路径`、`设置值_路径` 配套使用。

    设计特性：
        - 支持字符串路径与路径序列两种形式；
        - 自动根据下一段路径推断应补齐 dict 还是 list；
        - 若中途遇到无法继续下钻的非容器对象，则返回 False；
        - 对已有且合法的路径不做破坏性修改；
        - 不抛出任何异常，适合作为底层结构保障函数使用。

    行为说明：
        - 路径已存在且结构可继续遍历   → 返回 True；
        - 路径缺失且已成功补齐         → 返回 True；
        - 路径非法或结构冲突           → 返回 False。

    Args:
        数据 (Any): 通常为 dict 或 list 的嵌套结构。
        键路径 (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

        if not isinstance(数据, (dict, list)):
            return False

        当前 = 数据

        for 索引位置, 段 in enumerate(路径列表):
            是否最后一段 = 索引位置 == len(路径列表) - 1
            下一段 = None if 是否最后一段 else 路径列表[索引位置 + 1]

            if isinstance(当前, dict):
                键名 = str(段) if 键转字符串 else 段

                if 键名 not in 当前:
                    if 是否最后一段:
                        当前[键名] = {}
                    else:
                        当前[键名] = [] if _是否应创建列表(下一段) else {}

                if not isinstance(当前[键名], (dict, list)):
                    return 是否最后一段

                当前 = 当前[键名]
                continue

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

                if 目标索引 < 0:
                    return False

                while len(当前) <= 目标索引:
                    当前.append(None)

                if 当前[目标索引] is None:
                    if 是否最后一段:
                        当前[目标索引] = {}
                    else:
                        当前[目标索引] = [] if _是否应创建列表(下一段) else {}

                if not isinstance(当前[目标索引], (dict, list)):
                    return 是否最后一段

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

            return False

        return True
    except Exception:
        return False