def progress_bar(*, progress: int, maximum: int, per: int = 1) -> str:
    """Constructs a progress bar.

    .. versionadded:: 2.0

    .. versionchanged:: 3.0

        * Re-ordered the arguments to ``progress``, ``maximum``,
        and ``per``.
        * Raise :exc:`ValueError` if any of the following apply:

            * ``maximum`` is negative or 0.
            * ``per`` is negative, 0, or greater than ``maximum``.
            * ``progress`` is less than maximum.

    Parameters
    ----------
    progress: :class:`float`
        The value the progress bar is currently at.

        .. versionchanged:: 3.0
            This is now a keyword-only argument.
    maximum: :class:`int`
        The maximum value of the progress bar.

        .. versionchanged:: 3.0
            This is now a keyword-only argument.
    per: :class:`int`
        The value of each portion of the progress bar.
        Defaults to ``1``.

        .. versionchanged:: 3.0
            This is now a keyword-only argument.

    Returns
    -------
    :class:`str`
        The constructed progress bar.

    Raises
    ------
    ValueError
        An invalid ``per``, ``maximum``, or ``progress``
        value was given.
    """
    if maximum <= 0:
        raise ValueError(f"invalid maximum {maximum} (must be > 0)")

    if per > maximum or per <= 0:
        raise ValueError(f"invalid per {per} (must be > 0 and < `maximum` value)")

    if progress > maximum:
        raise ValueError(f"invalid progress {progress} (must be < `maximum` value)")

    total = maximum // per
    filled = int(progress // per)

    # Have to subtract in these cases to account for the
    # the edge pieces, since we're doing the simple-but-
    # not-so-simple approach of calculating the body.

    FR = "<:pb_r_f:786093987336421376>"
    EL = "<:pb_l_e:786093986745942037>"
    FB = "<:pb_b_f:786093986703605830>"
    EB = "<:pb_b_e:786093986233188363>"

    if filled == total:
        FL = "<:pb_l_f:786093987076374548>"
        return FR + FB * (total - 2) + FL

    if filled == 0:
        ER = "<:pb_r_e:786093986838347836>"
        return ER + EB * (total - 2) + EL

    return FR + FB * (filled - 1) + EB * (total - filled - 1) + EL