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

from remedapy.decorator import make_data_last

MuliplyableByInt = TypeVar('MuliplyableByInt', int, float, str)


@overload
def multiply(a: int, /) -> Callable[[MuliplyableByInt], MuliplyableByInt]: ...


@overload
def multiply(a: float, /) -> Callable[[int | float], float]: ...


@overload
def multiply(a: int, b: int, /) -> int: ...


@overload
def multiply(a: int | float, b: int | float, /) -> float: ...


@overload
def multiply(a: int, b: str, /) -> str: ...


# TODO: string times number
# TODO: list times number
# TODO: T times T
@make_data_last
def multiply(
    a: int | float,
    b: int | float,
    /,
) -> int | float | Callable[[int | float], int | float] | Callable[[MuliplyableByInt], MuliplyableByInt]:
    """
    Multiplies two numbers.

    Alias for `operator.mul` (*) - `__mul__` magic method.

    Parameters
    ----------
    a : int | float | T
        First thing (positional-only).
    b : int | float | T
        Second thing (positional-only).

    Returns
    -------
    int | float | str | result of multiplying T by T
        Product of a and b.

    Examples
    --------
    Data first:
    >>> R.multiply(2, 3)
    6

    Data last:
    >>> R.multiply(3)(2)
    6
    >>> R.multiply(0.1)(0.2)
    0.02...

    """
    return a * b
