import re
import sys

from ..test_managercli import TestCliProxyCommand
from subscription_manager import managercli
from subscription_manager.overrides import Override

from ..fixture import Capture

from unittest.mock import patch


class TestOverrideCommand(TestCliProxyCommand):
    command_class = managercli.OverrideCommand

    def _test_exception(self, args):
        self.cc.main(args)
        self.assertRaises(SystemExit, self.cc._validate_options)

    def test_bad_add_format(self):
        self._test_exception(["--add", "hello"])
        self._test_exception(["--add", "hello:"])

    def test_add_and_remove_with_no_repo(self):
        self._test_exception(["--add", "hello:world"])
        self._test_exception(["--remove", "hello"])

    def test_add_and_remove_with_list(self):
        self._test_exception(["--add", "x:y", "--repo", "x", "--list"])
        self._test_exception(["--remove", "y", "--repo", "x", "--list"])

    def test_add_and_remove_with_remove_all(self):
        self._test_exception(["--add", "x:y", "--repo", "x", "--remove-all"])
        self._test_exception(["--remove", "y", "--repo", "x", "--remove-all"])

    def test_list_and_remove_all_mutuall_exclusive(self):
        self._test_exception(["--list", "--remove-all"])

    def test_no_bare_repo(self):
        self._test_exception(["--repo", "x"])

    def test_list_by_default(self):
        with patch.object(sys, "argv", ["subscription-manager", "repo-override"]):
            self.cc.main([])
            self.cc._validate_options()
            self.assertTrue(self.cc.options.list)

    def test_list_by_default_with_options_from_super_class(self):
        self.cc.main(["--proxy", "http://www.example.com", "--proxyuser", "foo", "--proxypassword", "bar"])
        self.cc._validate_options()
        self.assertTrue(self.cc.options.list)

    def test_add_with_multiple_colons(self):
        self.cc.main(["--repo", "x", "--add", "url:http://example.com"])
        self.cc._validate_options()
        self.assertEqual(self.cc.options.additions, {"url": "http://example.com"})

    def test_add_and_remove_with_multi_repos(self):
        self.cc.main(["--repo", "x", "--repo", "y", "--add", "a:b", "--remove", "a"])
        self.cc._validate_options()
        self.assertEqual(self.cc.options.repos, ["x", "y"])
        self.assertEqual(self.cc.options.additions, {"a": "b"})
        self.assertEqual(self.cc.options.removals, ["a"])

    def test_remove_empty_arg(self):
        self._test_exception(["--repo", "x", "--remove", ""])

    def test_remove_multiple_args_empty_arg(self):
        self._test_exception(["--repo", "x", "--remove", "foo", "--remove", ""])

    def test_add_empty_arg(self):
        self._test_exception(["--repo", "x", "--add", ""])

    def test_add_empty_name(self):
        self._test_exception(["--repo", "x", "--add", ":foo"])

    def test_add_multiple_args_empty_arg(self):
        self._test_exception(["--repo", "x", "--add", "foo:bar", "--add", ""])

    def test_list_and_remove_all_work_with_repos(self):
        self.cc.main(["--repo", "x", "--list"])
        self.cc._validate_options()
        self.cc.main(["--repo", "x", "--remove-all"])
        self.cc._validate_options()

    def _build_override(self, repo, name=None, value=None):
        data = {"contentLabel": repo}
        if name:
            data["name"] = name
        if value:
            data["value"] = value
        return data

    def test_list_function(self):
        data = [
            Override("x", "hello", "world"),
            Override("x", "blast-off", "space"),
            Override("y", "goodbye", "earth"),
            Override("z", "greetings", "mars"),
        ]
        with Capture() as cap:
            self.cc._list(data, None)
            output = cap.out
            self.assertTrue(re.search(r"Repository: x", output))
            self.assertTrue(re.search(r"\s+hello:\s+world", output))
            self.assertTrue(re.search(r"\s+blast-off:\s+space", output))
            self.assertTrue(re.search(r"Repository: y", output))
            self.assertTrue(re.search(r"\s+goodbye:\s+earth", output))
            self.assertTrue(re.search(r"Repository: z", output))
            self.assertTrue(re.search(r"\s+greetings:\s+mars", output))

    def test_list_specific_repos(self):
        data = [Override("x", "hello", "world"), Override("z", "greetings", "mars")]
        with Capture() as cap:
            self.cc._list(data, ["x"])
            output = cap.out
            self.assertTrue(re.search(r"Repository: x", output))
            self.assertTrue(re.search(r"\s+hello:\s+world", output))
            self.assertFalse(re.search(r"Repository: z", output))

    def test_list_nonexistant_repos(self):
        data = [Override("x", "hello", "world")]
        with Capture() as cap:
            self.cc._list(data, ["x", "z"])
            output = cap.out
            self.assertTrue(re.search(r"Nothing is known about 'z'", output))
            self.assertTrue(re.search(r"Repository: x", output))
            self.assertTrue(re.search(r"\s+hello:\s+world", output))
