import pytest

from commitizen.version_schemes import Pep440, VersionProtocol
from tests.utils import VersionSchemeTestArgs


@pytest.mark.parametrize(
    "version_args, expected_version",
    [
        (
            VersionSchemeTestArgs(
                current_version="0.1.1",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.1.2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.1.1",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.2.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.1.1",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.9.0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.9.1a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.9.0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.10.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.9.0",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.9.0",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=1,
                devrelease=None,
            ),
            "1.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a2",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a2",
                increment=None,
                prerelease="beta",
                prerelease_offset=1,
                devrelease=None,
            ),
            "1.0.0b1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0beta1",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0rc0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc1",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0rc2",
        ),
        # weird cases
        (
            VersionSchemeTestArgs(
                current_version="1.1",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1a0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1a0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=1,
                devrelease=None,
            ),
            "1.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1",
                increment=None,
                prerelease="beta",
                prerelease_offset=1,
                devrelease=None,
            ),
            "1.0.0b1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1beta",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0alpha1",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0rc0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc1+e20d7b57f3eb",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0",
        ),
        # simple flow
        (
            VersionSchemeTestArgs(
                current_version="0.1.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.1.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.1.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=1,
            ),
            "0.1.1.dev1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.1.1",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.2.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.2.0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.2.0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=1,
            ),
            "0.3.0.dev1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.1a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.1a0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.1a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=1,
                devrelease=None,
            ),
            "0.3.1a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.1a0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=1,
                devrelease=None,
            ),
            "0.3.1a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.1a0",
                increment=None,
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.3.1",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.3.2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.4.2",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a1",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a1",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=1,
            ),
            "1.0.0a2.dev1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a2.dev0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=1,
            ),
            "1.0.0a3.dev1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a2.dev0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=0,
            ),
            "1.0.0a3.dev0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a1",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b0",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b1",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0rc0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0rc1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=1,
            ),
            "1.0.0rc1.dev1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a3.dev0",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.0b0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.1",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.2",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.2.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.2.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.2.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.2.1",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        # linear prerelease cases
        (
            VersionSchemeTestArgs(
                current_version="0.1.1b1",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.1.1b2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.1.1rc0",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.1.1rc1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="0.1.1rc0",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "0.1.1rc1",
        ),
        # prerelease cases
        (
            VersionSchemeTestArgs(
                current_version="3.3.3",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.3.4a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.3.4a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.3.4a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.3.4a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.4.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.4.0a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.4.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.4.0a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.4.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.4.0a2",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.0.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="4.0.0a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="4.0.0a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.0.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="4.0.0a2",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.0.0a3",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.1a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.1a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a2",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a1",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a2",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a3",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a3",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a1",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a2",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a2",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a3",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a3",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a4",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a4",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a5",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a5",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0a6",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0b1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0b1",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="1.0.1a0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.1a0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.1a0",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.1.0a0",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a0",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="2.0.0a0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="3.0.0a1",
                increment=None,
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.0.0b1",
                increment=None,
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.0.0rc1",
                increment=None,
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="3.1.4",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.1.4a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.1.4",
                increment=None,
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.1.4b0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.1.4",
                increment=None,
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.1.4rc0",
        ),
        #
        (
            VersionSchemeTestArgs(
                current_version="3.1.4",
                increment=None,
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.1.4a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.1.4a0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.1.4a1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.1.4a0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.2.0a0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="3.1.4a0",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.0.0a0",
        ),
    ],
)
def test_bump_pep440_version(version_args, expected_version):
    assert (
        str(
            Pep440(version_args.current_version).bump(
                increment=version_args.increment,
                prerelease=version_args.prerelease,
                prerelease_offset=version_args.prerelease_offset,
                devrelease=version_args.devrelease,
            )
        )
        == expected_version
    )


@pytest.mark.parametrize(
    "version_args, expected_version",
    [
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="1.0.0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0",
        ),
        # with exact_increment=False: "1.0.0b0"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a1",
                increment="PATCH",
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1b0",
        ),
        # with exact_increment=False: "1.0.0b1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b0",
                increment="PATCH",
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1b0",
        ),
        # with exact_increment=False: "1.0.0rc0"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b1",
                increment="PATCH",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1rc0",
        ),
        # with exact_increment=False: "1.0.0-rc1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment="PATCH",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.0.1rc0",
        ),
        # with exact_increment=False: "1.0.0rc1-dev1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment="PATCH",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=1,
            ),
            "1.0.1rc0.dev1",
        ),
        # with exact_increment=False: "1.0.0b0"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0a1",
                increment="MINOR",
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0b0",
        ),
        # with exact_increment=False: "1.0.0b1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b0",
                increment="MINOR",
                prerelease="beta",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0b0",
        ),
        # with exact_increment=False: "1.0.0b1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0a0",
        ),
        # with exact_increment=False: "1.0.0rc0"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0b1",
                increment="MINOR",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0rc0",
        ),
        # with exact_increment=False: "1.0.0rc1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment="MINOR",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=None,
            ),
            "1.1.0rc0",
        ),
        # with exact_increment=False: "1.0.0rc1-dev1"
        (
            VersionSchemeTestArgs(
                current_version="1.0.0rc0",
                increment="MINOR",
                prerelease="rc",
                prerelease_offset=0,
                devrelease=1,
            ),
            "1.1.0rc0.dev1",
        ),
        # with exact_increment=False: "2.0.0"
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0",
        ),
        # with exact_increment=False: "2.0.0"
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.1.0",
        ),
        # with exact_increment=False: "2.0.0"
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.1",
        ),
        # same with exact_increment=False
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="MAJOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "3.0.0a0",
        ),
        # with exact_increment=False: "2.0.0b1"
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="MINOR",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.1.0a0",
        ),
        # with exact_increment=False: "2.0.0b1"
        (
            VersionSchemeTestArgs(
                current_version="2.0.0b0",
                increment="PATCH",
                prerelease="alpha",
                prerelease_offset=0,
                devrelease=None,
            ),
            "2.0.1a0",
        ),
    ],
)
def test_bump_pep440_version_force(version_args, expected_version):
    assert (
        str(
            Pep440(version_args.current_version).bump(
                increment=version_args.increment,
                prerelease=version_args.prerelease,
                prerelease_offset=version_args.prerelease_offset,
                devrelease=version_args.devrelease,
                exact_increment=True,
            )
        )
        == expected_version
    )


@pytest.mark.parametrize(
    "version_args, expected_version",
    [
        (
            VersionSchemeTestArgs(
                current_version="4.5.0+0.1.0",
                increment="PATCH",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.5.0+0.1.1",
        ),
        (
            VersionSchemeTestArgs(
                current_version="4.5.0+0.1.1",
                increment="MINOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.5.0+0.2.0",
        ),
        (
            VersionSchemeTestArgs(
                current_version="4.5.0+0.2.0",
                increment="MAJOR",
                prerelease=None,
                prerelease_offset=0,
                devrelease=None,
            ),
            "4.5.0+1.0.0",
        ),
    ],
)
def test_bump_pep440_version_local(version_args, expected_version):
    assert (
        str(
            Pep440(version_args.current_version).bump(
                increment=version_args.increment,
                prerelease=version_args.prerelease,
                prerelease_offset=version_args.prerelease_offset,
                devrelease=version_args.devrelease,
                is_local_version=True,
            )
        )
        == expected_version
    )


def test_pep440_scheme_property():
    version = Pep440("0.0.1")
    assert version.scheme is Pep440


def test_pep440_implement_version_protocol():
    assert isinstance(Pep440("0.0.1"), VersionProtocol)
