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


class TestHaproxyServerCommands(CommandTestCase):
    def setUp(self):
        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_create_OK = {"result": "saved", "uuid": "85282721-934c-42be-ba4d-a93cbfda26af"}
        self._api_data_fixtures_create_ERROR = {
            "result": "failed",
            "validations": {"server.weight": "Please specify a value between 0 and 256."},
        }
        self._api_data_fixtures_update_OK = {"result": "saved"}
        self._api_data_fixtures_update_NOT_EXISTS = {"result": "failed"}
        self._api_data_fixtures_delete_NOT_FOUND = {"result": "not found"}
        self._api_data_fixtures_delete_OK = {"result": "deleted"}
        self._api_data_fixtures_list_EMPTY = {"haproxy": {"servers": {"server": []}}}
        self._api_data_fixtures_list = self._read_json_fixture("fixtures/model_data.json", base_dir=os.path.dirname(__file__))
        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.server.ApiClient.execute")
    def test_list(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list,
            ],
            server,
            ["list", "-o", "plain"],
        )

        self.assertEqual(
            (
                "15e47988-d6fd-498f-9583-cd13a37408bd 0 my_new_testserver template 10.0.0.1 9091 test 0 0 10\n"
                "cbb43680-dd44-4f3d-b64b-8ef64c97be96 0 my_new_testserver template 10.0.0.1 9091 test 1 0 10\n"
                "dd74172b-d5c7-4d44-9ce3-667675a1e780 1 server1 template 192.168.56.1 8081  1 1 \n"
                "28cfa25d-74b2-4a22-9f4a-d5923fb1394d 1 server2 static    0 1 \n"
                "46e159c3-c96d-45a1-8c81-f963c40e1e9f 1 server4 static 10.0.0.1 9000  1 1 15\n"
                "0f2f3bfd-8661-4e86-b2a6-2ce6a3420a48 1 server50 static    1 1 \n"
            ),
            result.output,
        )

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_list_EMPTY(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list_EMPTY,
            ],
            server,
            ["list", "-o", "plain"],
        )

        self.assertIn("", result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_show_NOT_FOUND(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list,
            ],
            server,
            ["show", "b468c719-89db-45a8-bd02-b081246dc002"],
        )
        self.assertIn("", result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_show_EMPTY_STRING(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list,
            ],
            server,
            ["show", ""],
        )
        self.assertIn("", result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_show(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list,
            ],
            server,
            ["show", "15e47988-d6fd-498f-9583-cd13a37408bd", "-o", "plain", "-c", "enabled,name,Resolver"],
        )

        self.assertIn(("0 my_new_testserver resolver1\n"), result.output)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_create_OK(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_list,
                self._api_data_fixtures_create_OK,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "create",
                "my_test_server",
                "--no-enabled",
                "--type",
                "template",
                "--description",
                "test",
                "--address",
                "10.0.0.1",
                "--port",
                "9091",
                "--mode",
                "backup",
                "--no-ssl",
                "--no-sslVerify",
                "--weight",
                "10",
                "--checkInterval",
                "10",
                "--source",
                "10.0.0.5",
                "--linkedResolver",
                "resolver1",
            ],
        )

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

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_create_ERROR(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_create_ERROR,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "create",
                "my_test_server",
                "--weight",
                "10000",
            ],
        )

        self.assertIn(
            (
                "Error: {'result': 'failed', "
                "'validations': {'server.weight': 'Please specify a value between 0 and 256.'}}\n"
            ),
            result.output,
        )
        self.assertEqual(1, result.exit_code)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_update_OK(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_update_OK,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "update",
                "85282721-934c-42be-ba4d-a93cbfda26af",
                "--linkedResolver",
                "cea8f031-9aba-4f6e-86c2-f5f5f27a10b8",
                "--enabled",
            ],
        )

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

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_update_NOT_EXISTS(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_update_NOT_EXISTS,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "update",
                "99282721-934c-42be-ba4d-a93cbfda2644",
                "--no-enabled",
            ],
        )

        self.assertIn(("Error: {'result': 'failed'}\n"), result.output)
        self.assertEqual(1, result.exit_code)

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_delete_OK(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_delete_OK,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "delete",
                "85282721-934c-42be-ba4d-a93cbfda26af",
            ],
        )

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

    @patch("opnsense_cli.commands.plugin.haproxy.server.ApiClient.execute")
    def test_delete_NOT_FOUND(self, api_response_mock: Mock):
        result = self._opn_cli_command_result(
            api_response_mock,
            [
                self._api_data_fixtures_delete_NOT_FOUND,
                self._api_data_fixtures_configtest_OK,
                self._api_data_fixtures_reconfigure_OK,
            ],
            server,
            [
                "delete",
                "99282721-934c-42be-ba4d-a93cbfda2644",
            ],
        )

        self.assertIn("Error: {'result': 'not found'}\n", result.output)
        self.assertEqual(1, result.exit_code)
