from collections.abc import Callable
from typing import TypeVar, overload

from remedapy.decorator import make_data_last
from remedapy.util import NonPositiveInt

TNum = TypeVar('TNum', int, float)

real_round = round


@overload
def round(precision: NonPositiveInt, /) -> Callable[[int | float], int]: ...


@overload
def round(precision: int, /) -> Callable[[TNum], TNum]: ...


@overload
def round(value: int | float, precision: NonPositiveInt, /) -> int: ...


@overload
def round(value: TNum, precision: int, /) -> TNum: ...


@make_data_last
def round(
    value: int | float,
    precision: int,
    /,
) -> int | float:
    """
    Rounds a given number to a specific precision.

    Alias for built-in `round`.

    Parameters
    ----------
    value : int | float
        Number to round (positional-only).
    precision : int
        Desired precision (positional-only).

    Returns
    -------
    int | float
        rounded value, int if precision is non-positive, otherwise float.

    Examples
    --------
    Data first:
    >>> R.round(123.9876, 3)
    123.988
    >>> R.round(8541.1, -1)
    8540

    Data last:
    >>> R.round(1)(483.22243)
    483.2
    >>> R.round(-3)(456789)
    457000

    """
    result = real_round(value, precision)
    if precision <= 0:
        return int(result)
    return result
