import os
from tempfile import mkdtemp

from pytest_mock import MockerFixture

from git_machete.code_hosting import OrganizationAndRepository
from git_machete.gitlab import GitLabClient
from tests.base_test import BaseTest, GitRepositorySandbox
from tests.mockers import (assert_failure, assert_success, launch_command,
                           rewrite_branch_layout_file)
from tests.mockers_code_hosting import mock_from_url
from tests.mockers_gitlab import (MockGitLabAPIState,
                                  mock_gitlab_token_for_domain_fake,
                                  mock_gitlab_token_for_domain_none,
                                  mock_mr_json, mock_projects, mock_urlopen)


class TestGitLabCheckoutMRs(BaseTest):
    @staticmethod
    def gitlab_api_state_for_test_checkout_mrs() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='chore/redundant_checks', base='restrict_access', number=18),
            mock_mr_json(head='restrict_access', base='allow-ownership-link', number=17),
            mock_mr_json(head='allow-ownership-link', base='bugfix/feature', number=12),
            mock_mr_json(head='bugfix/feature', base='enhance/feature', number=6),
            mock_mr_json(head='enhance/add_user', base='develop', number=19),
            mock_mr_json(head='testing/add_user', base='bugfix/add_user', number=22),
            mock_mr_json(head='chore/comments', base='testing/add_user', number=24),
            mock_mr_json(head='ignore-trailing', base='hotfix/add-trigger', number=3),
            mock_mr_json(head='bugfix/remove-n-option', base='develop', number=5, state='closed', repo_id=2)
        )

    def test_gitlab_checkout_mrs(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'git_machete.gitlab.GitLabToken.for_domain', mock_gitlab_token_for_domain_none)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.gitlab_api_state_for_test_checkout_mrs()))

        (
            self.repo_sandbox.new_branch("root")
            .commit("initial commit")
            .new_branch("develop")
            .commit("first commit")
            .push()
            .new_branch("enhance/feature")
            .commit("introduce feature")
            .push()
            .new_branch("bugfix/feature")
            .commit("bugs removed")
            .push()
            .new_branch("allow-ownership-link")
            .commit("fixes")
            .push()
            .new_branch('restrict_access')
            .commit('authorized users only')
            .push()
            .new_branch("chore/redundant_checks")
            .commit('remove some checks')
            .push()
            .check_out("root")
            .new_branch("master")
            .commit("Master commit")
            .push()
            .new_branch("hotfix/add-trigger")
            .commit("HOTFIX Add the trigger")
            .push()
            .new_branch("ignore-trailing")
            .commit("Ignore trailing data")
            .push()
            .delete_branch("root")
            .new_branch('chore/fields')
            .commit("remove outdated fields")
            .push()
            .check_out('develop')
            .new_branch('enhance/add_user')
            .commit('allow externals to add users')
            .push()
            .new_branch('bugfix/add_user')
            .commit('first round of fixes')
            .push()
            .new_branch('testing/add_user')
            .commit('add test set for add_user feature')
            .push()
            .new_branch('chore/comments')
            .commit('code maintenance')
            .push()
            .check_out('master')
        )
        for branch in ('chore/redundant_checks', 'restrict_access', 'allow-ownership-link', 'bugfix/feature', 'enhance/add_user',
                       'testing/add_user', 'chore/comments', 'bugfix/add_user'):
            self.repo_sandbox.delete_branch(branch)

        body: str = \
            """
            master
                hotfix/add-trigger
                    ignore-trailing
                        chore/fields
            develop
                enhance/feature
                    bugfix/feature
                        allow-ownership-link
                            restrict_access
                                chore/redundant_checks
            """
        rewrite_branch_layout_file(body)

        # not broken chain of pull requests (root found in dependency tree)
        launch_command('gitlab', 'checkout-mrs', '18')
        assert_success(
            ["status"],
            """
            master
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3 (some_other_user) rebase=no push=no
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
              |
              o-bugfix/feature  MR !6 (some_other_user) rebase=no push=no
                |
                o-allow-ownership-link  MR !12 (some_other_user) rebase=no push=no
                  |
                  o-restrict_access  MR !17 (some_other_user) rebase=no push=no
                    |
                    o-chore/redundant_checks *  MR !18 (some_other_user) rebase=no push=no
            """
        )
        # broken chain of pull requests (add new root)
        launch_command('gitlab', 'checkout-mrs', '24')
        assert_success(
            ["status"],
            """
            master
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3 (some_other_user) rebase=no push=no
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
              |
              o-bugfix/feature  MR !6 (some_other_user) rebase=no push=no
                |
                o-allow-ownership-link  MR !12 (some_other_user) rebase=no push=no
                  |
                  o-restrict_access  MR !17 (some_other_user) rebase=no push=no
                    |
                    o-chore/redundant_checks  MR !18 (some_other_user) rebase=no push=no

            bugfix/add_user
            |
            o-testing/add_user  MR !22 (some_other_user) rebase=no push=no
              |
              o-chore/comments *  MR !24 (some_other_user) rebase=no push=no
            """
        )

        # broken chain of pull requests (branches already added)
        launch_command('gitlab', 'checkout-mrs', '24')
        assert_success(
            ["status"],
            """
            master
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3 (some_other_user) rebase=no push=no
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
              |
              o-bugfix/feature  MR !6 (some_other_user) rebase=no push=no
                |
                o-allow-ownership-link  MR !12 (some_other_user) rebase=no push=no
                  |
                  o-restrict_access  MR !17 (some_other_user) rebase=no push=no
                    |
                    o-chore/redundant_checks  MR !18 (some_other_user) rebase=no push=no

            bugfix/add_user
            |
            o-testing/add_user  MR !22 (some_other_user) rebase=no push=no
              |
              o-chore/comments *  MR !24 (some_other_user) rebase=no push=no
            """
        )

        # all MRs
        launch_command('gitlab', 'checkout-mrs', '--all')
        assert_success(
            ["status"],
            """
            master
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3 (some_other_user) rebase=no push=no
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
            | |
            | o-bugfix/feature  MR !6 (some_other_user) rebase=no push=no
            |   |
            |   o-allow-ownership-link  MR !12 (some_other_user) rebase=no push=no
            |     |
            |     o-restrict_access  MR !17 (some_other_user) rebase=no push=no
            |       |
            |       o-chore/redundant_checks  MR !18 (some_other_user) rebase=no push=no
            |
            o-enhance/add_user  MR !19 (some_other_user) rebase=no push=no

            bugfix/add_user
            |
            o-testing/add_user  MR !22 (some_other_user) rebase=no push=no
              |
              o-chore/comments *  MR !24 (some_other_user) rebase=no push=no
            """
        )

        # check against wrong MR number
        org_repo = OrganizationAndRepository.from_url(
            domain=GitLabClient.DEFAULT_GITLAB_DOMAIN,
            url=self.repo_sandbox.remote_path)

        assert org_repo is not None
        expected_error_message = f"MR !100 is not found in project {org_repo.organization}/{org_repo.repository}"
        assert_failure(['gitlab', 'checkout-mrs', '100'], expected_error_message)

        assert_failure(['gitlab', 'checkout-mrs', '19', '100'], expected_error_message)

        expected_msg = "Checking for open GitLab MRs... OK\n"
        assert_success(['gitlab', 'checkout-mrs', '--by', 'some_other_user'], expected_msg)

        # Check against closed pull request with source branch deleted from remote
        other_local_path = mkdtemp()
        self.repo_sandbox.new_repo(GitRepositorySandbox.second_remote_path, bare=True)
        (
            self.repo_sandbox
            .new_repo(other_local_path, bare=False)
            .add_remote("origin", GitRepositorySandbox.second_remote_path)
            .new_branch('main')
            .commit('initial commit')
            .push()
        )

        expected_error_message = "Could not check out MR !5 because branch bugfix/remove-n-option " \
                                 "is already deleted from tester."
        assert_failure(['gitlab', 'checkout-mrs', '5'], expected_error_message)

        # Check against MR coming from fork
        (
            self.repo_sandbox
            .new_branch('bugfix/remove-n-option')
            .commit('first commit')
            .push()
            .chdir(self.repo_sandbox.local_path)
        )

        expected_msg = ("Checking for open GitLab MRs... OK\n"
                        "Warn: MR !5 is already closed.\n"
                        "MR !5 checked out at local branch bugfix/remove-n-option\n")
        assert_success(['gitlab', 'checkout-mrs', '5'], expected_msg)

        # Check against multiple MRs
        expected_msg = 'Checking for open GitLab MRs... OK\n'
        assert_success(['gitlab', 'checkout-mrs', '3', '12'], expected_msg)

    @staticmethod
    def gitlab_api_state_for_test_gitlab_checkout_mrs_fresh_repo() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='comments/add_docstrings', base='improve/refactor', number=2),
            mock_mr_json(head='restrict_access', base='allow-ownership-link', number=17),
            mock_mr_json(head='improve/refactor', base='chore/sync_to_docs', number=1),
            mock_mr_json(head='sphinx_export', base='comments/add_docstrings', number=23, state='closed', repo_id=2)
        )

    def test_gitlab_checkout_mrs_freshly_cloned(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.gitlab_api_state_for_test_gitlab_checkout_mrs_fresh_repo()))

        (
            self.repo_sandbox.new_branch("root")
            .commit("initial commit")
            .new_branch("develop")
            .commit("first commit")
            .push()
            .new_branch("chore/sync_to_docs")
            .commit("synchronize docs")
            .push()
            .new_branch("improve/refactor")
            .commit("refactor code")
            .push()
            .new_branch("comments/add_docstrings")
            .commit("docstring added")
            .push()
            .new_branch("sphinx_export")
            .commit("export docs to html")
            .push()
            .check_out("root")
            .new_branch("master")
            .commit("Master commit")
            .push()
            .delete_branch("root")
            .push()
        )
        for branch in ('develop', 'chore/sync_to_docs', 'improve/refactor', 'comments/add_docstrings'):
            self.repo_sandbox.delete_branch(branch)
        local_path = mkdtemp()
        self.repo_sandbox\
            .chdir(local_path)\
            .execute(f'git clone {self.repo_sandbox.remote_path}')\
            .chdir(os.path.join(local_path, os.listdir()[0]))

        for branch in ('develop', 'chore/sync_to_docs', 'improve/refactor', 'comments/add_docstrings'):
            self.repo_sandbox.delete_remote_branch(f"origin/{branch}")

        self.repo_sandbox.new_repo(GitRepositorySandbox.second_remote_path, bare=True)
        (
            self.repo_sandbox.new_repo(local_path, bare=False)
            .add_remote("origin", GitRepositorySandbox.second_remote_path)
            .new_branch('feature')
            .commit('initial commit')
            .push()
        )
        os.chdir(self.repo_sandbox.local_path)
        rewrite_branch_layout_file("master")
        expected_msg = ("Checking for open GitLab MRs... OK\n"
                        "MR !1 checked out at local branch improve/refactor\n"
                        "MR !2 checked out at local branch comments/add_docstrings\n")
        assert_success(
            ['gitlab', 'checkout-mrs', '2'],
            expected_msg
        )

        assert_success(
            ["status"],
            """
            master

            chore/sync_to_docs
            |
            o-improve/refactor  MR !1 (some_other_user) rebase=no push=no
              |
              o-comments/add_docstrings *  MR !2 (some_other_user) rebase=no push=no
            """
        )

        # Check against closed pull request
        self.repo_sandbox.delete_branch('sphinx_export')
        expected_msg = ("Checking for open GitLab MRs... OK\n"
                        "Warn: MR !23 is already closed.\n"
                        "MR !23 checked out at local branch sphinx_export\n")

        assert_success(
            ['gitlab', 'checkout-mrs', '23'],
            expected_msg
        )
        assert_success(
            ["status"],
            """
            master

            chore/sync_to_docs
            |
            o-improve/refactor  MR !1 (some_other_user) rebase=no push=no
              |
              o-comments/add_docstrings  MR !2 (some_other_user) rebase=no push=no
                |
                o-sphinx_export *
            """
        )

    @staticmethod
    def gitlab_api_state_for_test_gitlab_checkout_mrs_from_fork_with_deleted_repo() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='feature/allow_checkout', base='develop', number=2, repo_id=0, state='closed'),
            mock_mr_json(head='bugfix/allow_checkout', base='develop', number=3)
        )

    def test_gitlab_checkout_mrs_from_fork_with_deleted_repo(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'urllib.request.urlopen',
                          mock_urlopen(self.gitlab_api_state_for_test_gitlab_checkout_mrs_from_fork_with_deleted_repo()))

        (
            self.repo_sandbox.new_branch("root")
            .commit('initial master commit')
            .push()
            .new_branch('develop')
            .commit('initial develop commit')
            .push()
        )

        self.repo_sandbox \
            .chdir(self.repo_sandbox.remote_path)\
            .execute("git branch merge-requests/2/head develop")\
            .chdir(self.repo_sandbox.local_path)

        body: str = \
            """
            root
            develop
            """
        rewrite_branch_layout_file(body)
        expected_msg = ("Checking for open GitLab MRs... OK\n"
                        "Warn: MR !2 comes from fork and its project is already deleted. "
                        "No remote tracking data will be set up for feature/allow_checkout branch.\n"
                        "Warn: MR !2 is already closed.\n"
                        "MR !2 checked out at local branch feature/allow_checkout\n")
        assert_success(
            ['gitlab', 'checkout-mrs', '2'],
            expected_msg
        )

        assert 'feature/allow_checkout' == launch_command("show", "current").strip(), \
            ("Verify that 'git machete gitlab checkout-mrs' performs 'git checkout' to "
             "the source branch of given merge request.")

    @staticmethod
    def gitlab_api_state_for_test_gitlab_checkout_mrs_of_current_user_and_other_users() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='chore/redundant_checks', base='restrict_access', number=18),
            mock_mr_json(head='restrict_access', base='allow-ownership-link', number=17, user='gitlab_user'),
            mock_mr_json(head='allow-ownership-link', base='bugfix/feature', number=12),
            mock_mr_json(head='bugfix/feature', base='enhance/feature', number=6, user='gitlab_user'),
            mock_mr_json(head='enhance/add_user', base='develop', number=19),
            mock_mr_json(head='testing/add_user', base='bugfix/add_user', number=22, user='gitlab_user'),
            mock_mr_json(head='chore/comments', base='testing/add_user', number=24),
            mock_mr_json(head='ignore-trailing', base='hotfix/add-trigger', number=3, user='gitlab_user'),
            mock_mr_json(head='bugfix/remove-n-option', base='develop', number=5, state='closed', repo_id=2)
        )

    def test_gitlab_checkout_mrs_of_current_user_and_other_users(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'git_machete.gitlab.GitLabToken.for_domain', mock_gitlab_token_for_domain_fake)
        self.patch_symbol(mocker, 'urllib.request.urlopen',
                          mock_urlopen(self.gitlab_api_state_for_test_gitlab_checkout_mrs_of_current_user_and_other_users()))

        (
            self.repo_sandbox.new_branch("root")
            .commit("initial commit")
            .new_branch("develop")
            .commit("first commit")
            .push()
            .new_branch("enhance/feature")
            .commit("introduce feature")
            .push()
            .new_branch("bugfix/feature")
            .commit("bugs removed")
            .push()
            .new_branch("allow-ownership-link")
            .commit("fixes")
            .push()
            .new_branch('restrict_access')
            .commit('authorized users only')
            .push()
            .new_branch("chore/redundant_checks")
            .commit('remove some checks')
            .push()
            .check_out("root")
            .new_branch("master")
            .commit("Master commit")
            .push()
            .new_branch("hotfix/add-trigger")
            .commit("HOTFIX Add the trigger")
            .push()
            .new_branch("ignore-trailing")
            .commit("Ignore trailing data")
            .push()
            .delete_branch("root")
            .new_branch('chore/fields')
            .commit("remove outdated fields")
            .push()
            .check_out('develop')
            .new_branch('enhance/add_user')
            .commit('allow externals to add users')
            .push()
            .new_branch('bugfix/add_user')
            .commit('first round of fixes')
            .push()
            .new_branch('testing/add_user')
            .commit('add test set for add_user feature')
            .push()
            .new_branch('chore/comments')
            .commit('code maintenance')
            .push()
            .check_out('master')
        )
        for branch in ('chore/redundant_checks', 'restrict_access', 'allow-ownership-link', 'bugfix/feature', 'enhance/add_user',
                       'testing/add_user', 'chore/comments', 'bugfix/add_user'):
            self.repo_sandbox.delete_branch(branch)

        body: str = \
            """
            master
                hotfix/add-trigger
                    ignore-trailing
                        chore/fields
            develop
                enhance/feature
                    bugfix/feature
                        allow-ownership-link
                            restrict_access
                                chore/redundant_checks
            bugfix/add_user
                testing/add_user
                    chore/comments
            """
        rewrite_branch_layout_file(body)

        # test that `checkout-mrs` add `rebase=no push=no` qualifiers to branches associated with the MRs whose owner
        # is different than the current user
        launch_command('gitlab', 'checkout-mrs', '--all')
        assert_success(
            ["status"],
            """
            master *
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
            | |
            | o-bugfix/feature  MR !6
            |   |
            |   o-allow-ownership-link  MR !12 (some_other_user) rebase=no push=no
            |     |
            |     o-restrict_access  MR !17
            |       |
            |       o-chore/redundant_checks  MR !18 (some_other_user) rebase=no push=no
            |
            o-enhance/add_user  MR !19 (some_other_user) rebase=no push=no

            bugfix/add_user
            |
            o-testing/add_user  MR !22
              |
              o-chore/comments  MR !24 (some_other_user) rebase=no push=no
            """
        )

        # test that `checkout-mrs` doesn't overwrite annotation qualifiers but overwrites annotation text
        launch_command('anno', '-b=allow-ownership-link', 'branch_annotation rebase=no')
        launch_command('gitlab', 'checkout-mrs', '--all')
        assert_success(
            ["status"],
            """
            master *
            |
            o-hotfix/add-trigger
              |
              o-ignore-trailing  MR !3
                |
                o-chore/fields

            develop
            |
            o-enhance/feature
            | |
            | o-bugfix/feature  MR !6
            |   |
            |   o-allow-ownership-link  MR !12 (some_other_user) rebase=no
            |     |
            |     o-restrict_access  MR !17
            |       |
            |       o-chore/redundant_checks  MR !18 (some_other_user) rebase=no push=no
            |
            o-enhance/add_user  MR !19 (some_other_user) rebase=no push=no

            bugfix/add_user
            |
            o-testing/add_user  MR !22
              |
              o-chore/comments  MR !24 (some_other_user) rebase=no push=no
            """
        )

    def test_gitlab_checkout_mrs_misc_failures_and_warns(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(MockGitLabAPIState()))

        self.patch_symbol(mocker, 'git_machete.gitlab.GitLabToken.for_domain', mock_gitlab_token_for_domain_none)
        assert_success(
            ["gitlab", "checkout-mrs", "--all"],
            """
            Checking for open GitLab MRs... OK
            Warn: Currently there are no merge requests opened in project example-org/example-repo
            """
        )

        assert_success(
            ["gitlab", "checkout-mrs", "--by=gitlab_user"],
            """
            Checking for open GitLab MRs... OK
            Warn: User gitlab_user has no open merge request in project example-org/example-repo
            """
        )

        assert_failure(
            ["gitlab", "checkout-mrs", "--mine"],
            """
            Could not determine current user name, please check that the GitLab API token provided by one of the:
            \t1. GITLAB_TOKEN environment variable
            \t2. Content of the ~/.gitlab-token file
            \t3. Current auth token from the glab GitLab CLI
            is valid."""
        )

        self.patch_symbol(mocker, 'git_machete.gitlab.GitLabToken.for_domain', mock_gitlab_token_for_domain_fake)
        assert_success(
            ["gitlab", "checkout-mrs", "--mine"],
            """
            Checking for open GitLab MRs... OK
            Warn: Current user gitlab_user has no open merge request in project example-org/example-repo
            """
        )

    @staticmethod
    def gitlab_api_state_with_mr_cycle() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='bugfix/feature', base='chore/redundant_checks', number=6),
            mock_mr_json(head='chore/redundant_checks', base='restrict_access', number=18),
            mock_mr_json(head='restrict_access', base='allow-ownership-link', number=17),
            mock_mr_json(head='allow-ownership-link', base='chore/redundant_checks', number=12)
        )

    def test_gitlab_checkout_mrs_forming_a_cycle(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(self.gitlab_api_state_with_mr_cycle()))

        (
            self.repo_sandbox
            .new_branch("bugfix/feature")
            .commit("bugs removed")
            .push()
            .new_branch("allow-ownership-link")
            .commit("fixes")
            .push()
            .new_branch('restrict_access')
            .commit('authorized users only')
            .push()
            .new_branch("chore/redundant_checks")
            .commit('remove some checks')
            .push()
        )

        assert_failure(
            ['gitlab', 'checkout-mrs', '--all'],
            'There is a cycle between GitLab MRs: '
            'bugfix/feature -> chore/redundant_checks -> restrict_access -> allow-ownership-link -> chore/redundant_checks'
        )

    @staticmethod
    def gitlab_api_state_for_test_gitlab_checkout_mrs_single_mr() -> MockGitLabAPIState:
        return MockGitLabAPIState(
            mock_mr_json(head='develop', base='master', number=18)
        )

    def test_gitlab_checkout_mrs_remote_already_added(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
            self.gitlab_api_state_for_test_gitlab_checkout_mrs_single_mr()))
        (
            self.repo_sandbox
            .remove_remote("origin")
            .add_remote("origin-1", mock_projects()[1]['http_url_to_repo'])
        )
        assert_failure(
            ["gitlab", "checkout-mrs", "--all"],
            "Could not check out MR !18 because branch develop is already deleted from origin-1."
        )

        (
            self.repo_sandbox
            .remove_remote("origin-1")
            .add_remote("tester", 'https://gitlab.com/tester/lolxd.git')
        )
        assert_failure(
            ["gitlab", "checkout-mrs", "--all"],
            "Could not check out MR !18 because branch develop is already deleted from tester/tester."
        )

    def test_gitlab_checkout_mrs_org_and_repo_from_config(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
            self.gitlab_api_state_for_test_gitlab_checkout_mrs_single_mr()))

        (
            self.repo_sandbox
            .new_branch("master").commit()
            .new_branch("develop").commit().push()
        )

        self.repo_sandbox.set_remote_url("origin", "https://gitlab.com/example-org/example-repo.git")
        self.repo_sandbox.set_git_config_key('machete.gitlab.organization', "example-org")
        self.repo_sandbox.set_git_config_key('machete.gitlab.repository', "example-repo")
        assert_success(
            ['gitlab', 'checkout-mrs', '--all'],
            'Checking for open GitLab MRs... OK\n'
            'MR !18 checked out at local branch develop\n'
        )

    def test_gitlab_checkout_mrs_remote_from_config(self, mocker: MockerFixture) -> None:
        self.patch_symbol(mocker, 'git_machete.git_operations.GitContext.fetch_remote', lambda _self, _remote: None)
        self.patch_symbol(mocker, 'urllib.request.urlopen', mock_urlopen(
            self.gitlab_api_state_for_test_gitlab_checkout_mrs_single_mr()))

        (
            self.repo_sandbox
            .new_branch("master").commit()
            .new_branch("develop").commit().push()
        )

        self.repo_sandbox.set_remote_url("origin", "https://gitlab.com/example-org/example-repo.git")
        self.repo_sandbox.set_git_config_key('machete.gitlab.remote', "origin")
        assert_success(
            ['gitlab', 'checkout-mrs', '--all'],
            'Checking for open GitLab MRs... OK\n'
            'MR !18 checked out at local branch develop\n'
        )
