"""Compatibility utilities for cross-platform functionality."""

from __future__ import annotations

import os
import sys
from importlib.metadata import entry_points as _stdlib_entry_points
from typing import TYPE_CHECKING, Union

if sys.version_info >= (3, 10):
    from typing import TypeAlias
else:
    from typing_extensions import TypeAlias

if TYPE_CHECKING:
    from importlib.metadata import EntryPoint

    PathT: TypeAlias = os.PathLike[str] | str
else:
    PathT: TypeAlias = Union[os.PathLike, str]


if sys.version_info >= (3, 10):
    from importlib.metadata import entry_points as entry_points
else:

    def entry_points(
        **params: str,
    ) -> list[EntryPoint]:
        """Backport of entry_points(group=...) for Python 3.8/3.9."""
        groups = _stdlib_entry_points()
        group = params.get("group", "")
        name = params.get("name")
        eps = list(groups.get(group, []))  # type: ignore[call-overload]
        if name is not None:
            eps = [ep for ep in eps if ep.name == name]
        return eps


def normalize_path_for_assertion(path: str) -> str:
    """Normalize path separators for cross-platform assertions.

    On Windows, this converts backslashes to forward slashes to ensure
    path comparisons work correctly. On other platforms, returns the path unchanged.
    The length of the string is not changed by this operation.

    Args:
        path: The path string to normalize

    Returns:
        The path with normalized separators
    """
    return path.replace("\\", "/")


def strip_path_suffix(
    full_path: str, suffix_path: str, error_msg: str | None = None
) -> str:
    """Strip a suffix from a path, with cross-platform path separator handling.

    This function first normalizes path separators for Windows compatibility,
    then asserts that the full path ends with the suffix, and finally returns
    the path with the suffix removed. This is the common pattern used for
    computing parent directories from git output.

    Args:
        full_path: The full path string
        suffix_path: The suffix path to strip from the end
        error_msg: Optional custom error message for the assertion

    Returns:
        The prefix path with the suffix removed

    Raises:
        AssertionError: If the full path doesn't end with the suffix
    """
    normalized_full = normalize_path_for_assertion(full_path)

    if error_msg:
        assert normalized_full.endswith(suffix_path), error_msg
    else:
        assert normalized_full.endswith(suffix_path), (
            f"Path assertion failed: {full_path!r} does not end with {suffix_path!r}"
        )

    return full_path[: -len(suffix_path)]


def norm_real(path: PathT) -> str:
    """Normalize and resolve a path (combining normcase and realpath).

    This combines os.path.normcase() and os.path.realpath() to produce
    a canonical path string that is normalized for the platform and has
    all symbolic links resolved.

    Args:
        path: The path to normalize and resolve

    Returns:
        The normalized, resolved absolute path

    Examples:
        >>> norm_real("/path/to/../to/file.txt")  # doctest: +SKIP
        '/path/to/file.txt'
    """
    return os.path.normcase(os.path.realpath(path))
