import subprocess
import unittest
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from phs.modules.dns import DNSModule


class DNSModuleTests(unittest.TestCase):
    def context(self):
        config = MagicMock()
        config.hostname = "srv.example.test"
        config.getint.return_value = 900
        config.getbool.side_effect = lambda section, option, fallback=False: fallback
        database = MagicMock()
        database.get_state.return_value = "unknown"
        database.add_event.return_value = True
        notifier = MagicMock()
        logger = MagicMock()
        logger.getChild.return_value = MagicMock()
        return SimpleNamespace(
            config=config,
            database=database,
            notifier=notifier,
            logger=logger,
            tailer=MagicMock(),
        )

    @staticmethod
    def result(code=0, stdout="ok", stderr=""):
        return subprocess.CompletedProcess(["restartsrv_named"], code, stdout, stderr)

    def test_healthy_powerdns_uses_cpanel_wrapper_only(self):
        module = DNSModule(self.context())
        with patch.object(module, "_select_management_script", return_value=(Path("/scripts/restartsrv_named"), "PowerDNS")), \
             patch.object(module, "_run_command", return_value=self.result()) as runner:
            detail = module.run()
        runner.assert_called_once_with(Path("/scripts/restartsrv_named"), "--status")
        self.assertIn("PowerDNS activo", detail)
        module.ctx.notifier.send.assert_not_called()

    def test_failed_status_restarts_same_cpanel_wrapper(self):
        module = DNSModule(self.context())
        results = [
            self.result(1, "", "stopped"),
            self.result(0, "restarted"),
            self.result(0, "running"),
        ]
        with patch.object(module, "_select_management_script", return_value=(Path("/scripts/restartsrv_named"), "PowerDNS")), \
             patch.object(module, "_run_command", side_effect=results) as runner:
            detail = module.run()
        self.assertEqual(runner.call_args_list[0].args, (Path("/scripts/restartsrv_named"), "--status"))
        self.assertEqual(runner.call_args_list[1].args[:2], (Path("/scripts/restartsrv_named"), "--restart"))
        self.assertEqual(runner.call_args_list[2].args, (Path("/scripts/restartsrv_named"), "--status"))
        self.assertIn("reiniciado y verificado", detail)
        module.ctx.notifier.send.assert_called_once()

    def test_unrecovered_failure_marks_module_error(self):
        module = DNSModule(self.context())
        results = [self.result(1), self.result(1), self.result(1)]
        with patch.object(module, "_select_management_script", return_value=(Path("/scripts/restartsrv_named"), "PowerDNS")), \
             patch.object(module, "_run_command", side_effect=results):
            with self.assertRaises(RuntimeError):
                module.run()


if __name__ == "__main__":
    unittest.main()
