from collections.abc import Callable
from typing import overload

import remedapy as R
from remedapy.decorator import make_data_last


@overload
def to_snake_case(s: str, /) -> str: ...


@overload
def to_snake_case() -> Callable[[str], str]: ...


@make_data_last
def to_snake_case(s: str, /) -> str:
    """
    Makes the string snake case - lowercase, words separated by underscores.

    Parameters
    ----------
    s : str
        String to snake case (positional-only).

    Returns
    -------
    str
        Snake cased string.

    Examples
    --------
    Data first:
    >>> R.to_snake_case('hello world')
    'hello_world'
    >>> R.to_snake_case('__HELLO_WORLD__')
    'hello_world'

    Data last:
    >>> R.to_snake_case()('hello world')
    'hello_world'
    >>> R.to_snake_case()('__HELLO_WORLD__')
    'hello_world'

    """
    return R.pipe(
        s,
        R.to_lower_case,
        R.to_words,
        R.join('_'),
        R.uncapitalise,
    )
