import os
from unittest.mock import patch, Mock
from opnsense_cli.commands.plugin.haproxy import haproxy
from opnsense_cli.commands.test_base import CommandTestCase


class TestHaproxyConfigCommands(CommandTestCase):
    def setUp(self):
        self.setUpPyfakefs()
        self._api_data_fixtures_reconfigure_OK = {"status": "ok"}
        self._api_data_fixtures_reconfigure_FAILED = {"status": "failed"}
        self._api_data_fixtures_configtest_OK = {"result": "Configuration file is valid\n\n\n"}
        self._api_data_fixtures_configtest_FAILED = {"result": "Configuration file is invalid\n\n\n"}
        self._api_data_fixtures_config = {
            "response": ("#\n# Automatically generated configuration.\n# Do not edit this file manually.\n#\n\n")
        }

        self._api_data_fixtures_diff = {"response": "\n\n"}
        self._api_data_fixtures_export_OK = {
            "result": (
                "\tzip warning: name not matched: /usr/local/etc/haproxy.conf.staging\n"
                "  adding: tmp/haproxy/ (stored 0%)\n  adding: tmp/haproxy/ssl/ (stored 0%)\n"
                "  adding: tmp/haproxy/lua/ (stored 0%)\n  adding: tmp/haproxy/errorfiles/ (stored 0%)\n"
                "  adding: tmp/haproxy/mapfiles/ (stored 0%)\n\n\n"
            ),
            "filename": "haproxy_config_export.zip",
            "filetype": "application/zip",
            "content": (
                "UEsDBAoAAAAAAFWCBVMAAAAAAAAAAAAAAAAMABwAdG1wL2hhcHJveHkvVVQJAANiDwxhYg8MYXV4CwABBFAAAAAEUAAAA"
                "FBLAwQKAAAAAABwTApTAAAAAAAAAAAAAAAAEAAcAHRtcC9oYXByb3h5L3NzbC9VVAkAA2RIEmFiDwxhdXgLAAEEUAAAAARQAAAAUE"
                "sDBAoAAAAAAFWCBVMAAAAAAAAAAAAAAAAQABwAdG1wL2hhcHJveHkvbHVhL1VUCQADYg8MYWIPDGF1eAsAAQRQAAAABFAAAABQSwM"
                "ECgAAAAAAVYIFUwAAAAAAAAAAAAAAABcAHAB0bXAvaGFwcm94eS9lcnJvcmZpbGVzL1VUCQADYg8MYWIPDGF1eAsAAQRQAAAABFAA"
                "AABQSwMECgAAAAAAVYIFUwAAAAAAAAAAAAAAABUAHAB0bXAvaGFwcm94eS9tYXBmaWxlcy9VVAkAA2IPDGFiDwxhdXgLAAEEUAAAA"
                "ARQAAAAUEsBAh4DCgAAAAAAVYIFUwAAAAAAAAAAAAAAAAwAGAAAAAAAAAAQAOhBAAAAAHRtcC9oYXByb3h5L1VUBQADYg8MYXV4Cw"
                "ABBFAAAAAEUAAAAFBLAQIeAwoAAAAAAHBMClMAAAAAAAAAAAAAAAAQABgAAAAAAAAAEADoQUYAAAB0bXAvaGFwcm94eS9zc2wvVVQ"
                "FAANkSBJhdXgLAAEEUAAAAARQAAAAUEsBAh4DCgAAAAAAVYIFUwAAAAAAAAAAAAAAABAAGAAAAAAAAAAQAOhBkAAAAHRtcC9oYXBy"
                "b3h5L2x1YS9VVAUAA2IPDGF1eAsAAQRQAAAABFAAAABQSwECHgMKAAAAAABVggVTAAAAAAAAAAAAAAAAFwAYAAAAAAAAABAA6EHaA"
                "AAAdG1wL2hhcHJveHkvZXJyb3JmaWxlcy9VVAUAA2IPDGF1eAsAAQRQAAAABFAAAABQSwECHgMKAAAAAABVggVTAAAAAAAAAAAAAA"
                "AAFQAYAAAAAAAAABAA6EErAQAAdG1wL2hhcHJveHkvbWFwZmlsZXMvVVQFAANiDwxhdXgLAAEEUAAAAARQAAAAUEsFBgAAAAAFAAU"
                "AtgEAAHoBAAAAAA=="
            ),
        }

        self._api_client_args_fixtures = ["api_key", "api_secret", "https://127.0.0.1/api", True, "~/.opn-cli/ca.pem", 60]

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_show(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_config,
            ],
            haproxy,
            ["config", "show", "-o", "plain"],
        )

        self.assertIn(self._api_data_fixtures_config["response"], result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_diff(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_diff,
            ],
            haproxy,
            ["config", "diff", "-o", "plain"],
        )

        self.assertIn(self._api_data_fixtures_diff["response"], result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_test(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_configtest_OK,
            ],
            haproxy,
            ["config", "test", "-o", "plain"],
        )

        self.assertIn(self._api_data_fixtures_configtest_OK["result"], result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_apply_OK(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            haproxy,
            ["config", "apply", "-o", "plain"],
        )

        self.assertIn("ok\n", result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_apply_CONFIGTEST_FAILED(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_configtest_FAILED,
                self._api_data_fixtures_reconfigure_OK,
            ],
            haproxy,
            ["config", "apply", "-o", "plain"],
        )

        self.assertIn("Error:", result.output)
        self.assertEqual(1, result.exit_code)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_apply_APPLY_FAILED(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_FAILED,
            ],
            haproxy,
            ["config", "apply", "-o", "plain"],
        )

        self.assertIn("Error:", result.output)
        self.assertEqual(1, result.exit_code)

    @patch("opnsense_cli.commands.plugin.haproxy.config.ApiClient.execute")
    def test_download_OK(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_export_OK,
            ],
            haproxy,
            ["config", "download", "-o", "plain"],
        )

        self.assertIn("successfully saved zip to: ./haproxy_config_export.zip\n", result.output)
        self.assertTrue(os.path.exists("./haproxy_config_export.zip"))
