import platform
from pathlib import Path


def _expand_short_path(path: str) -> str:
    """Expand Windows 8.3 short paths to long form. No-op on non-Windows."""
    if platform.system() != "Windows":
        return path
    try:
        import ctypes

        buffer_size = ctypes.windll.kernel32.GetLongPathNameW(path, None, 0)
        if buffer_size == 0:
            return path
        buffer = ctypes.create_unicode_buffer(buffer_size)
        ctypes.windll.kernel32.GetLongPathNameW(path, buffer, buffer_size)
        return buffer.value
    except Exception:
        return path


def resolve_path(path: str) -> Path:
    expanded = _expand_short_path(path)
    return Path(expanded).resolve()


def is_path_allowed(path: str, allowed_dirs: list[str]) -> bool:
    if not allowed_dirs:
        return False
    resolved = resolve_path(path)
    for allowed in allowed_dirs:
        allowed_resolved = resolve_path(allowed)
        try:
            resolved.relative_to(allowed_resolved)
        except ValueError:
            continue
        else:
            return True
    return False


class PathNotAllowedError(Exception):
    def __init__(self, path: str, allowed_dirs: list[str]):
        self.path = path
        self.allowed_dirs = allowed_dirs
        resolved = resolve_path(path)
        resolved_allowed = [str(resolve_path(d)) for d in allowed_dirs]
        super().__init__(
            f"Access denied. Path '{resolved}' does not match any allowed directory: {resolved_allowed}"
        )


def validate_path(path: str, allowed_dirs: list[str]) -> Path:
    if not is_path_allowed(path, allowed_dirs):
        raise PathNotAllowedError(path, allowed_dirs)
    return resolve_path(path)
