import pytest
import sys

from psi_utils.argparse import ArgumentParser
from psi_utils.unittest_mock import MockApi, ANY_NOT_NONE
from typing import List


class TestArgparse_UnitTests:
    @pytest.mark.unit
    def test_add_argument(self):
        parser = ArgumentParser()
        parser.add_argument("-a", "--alpha", required=True, help="Test arg alpha")
        parser.add_argument("-b", "--beta", default="beta.default")
        subparser = parser.add_subparsers(required=True, dest="subcommand", title="subcommands")
        subparser.add_parser("cmd").add_argument("-g", "--gamma")
        self.set_sys_argv(["-a", "alpha.value", "cmd", "-g", "gamma.value"])
        parser.parse_args()
        parser.print_help()

    @pytest.mark.unit
    def test_parse_args_and_prompt(self):
        parser = ArgumentParser()
        parser.add_argument("-t", "--test", required=True, help="Test argument")
        self.set_sys_argv(["-t", "test.value"])
        with pytest.raises(OSError) as e_info:
            parser.parse_args_and_prompt()
        assert str(e_info.value).startswith("pytest: reading from stdin while output is captured")
        self.reset_sys_argv()

    @pytest.mark.unit
    def test_print_help(self):
        parser = ArgumentParser(default_help_format=True)
        parser.print_help()

        parser = ArgumentParser()
        parser.print_help()

        mock_file = MockApi()
        mock_file.on("write", ANY_NOT_NONE).return_val(None)
        parser.print_help(file=mock_file)
        mock_file.assert_expectations()

    def set_sys_argv(self, args: List[str]):
        self.__sys_argv = sys.argv
        sys.argv = [self.__sys_argv[0]] + args

    def reset_sys_argv(self):
        if hasattr(self, "__sys_argv"):
            sys.argv = self.__sys_argv
