from pathlib import Path
import re


_RELATIVE_PATH_PATTERN = re.compile(r"^[a-zA-Z0-9_.\-/]+$")


def normalize_relative_path(relative_path: str) -> str:
    return relative_path.replace("\\", "/").strip().lstrip("/")


def validate_relative_path(relative_path: str) -> None:
    if not relative_path:
        raise ValueError("相对路径不能为空")
    if ".." in relative_path:
        raise ValueError("相对路径不允许包含 ..")
    if Path(relative_path).is_absolute() or relative_path.startswith("/"):
        raise ValueError("相对路径不能为绝对路径")
    if not _RELATIVE_PATH_PATTERN.match(relative_path):
        raise ValueError("相对路径仅允许字母、数字、下划线、短横线、点和斜杠")


def resolve_under_root(root: Path, relative_path: str) -> Path:
    full = (root / relative_path).resolve()
    try:
        full.relative_to(root.resolve())
    except ValueError:
        raise ValueError("路径不允许超出存储根目录") from None
    return full
