# -*- coding:utf-8 -*-
"""
Unit tests for ddns.scheduler._base module
@author: NewFuture
"""

from __init__ import unittest, patch
from ddns.scheduler._base import BaseScheduler


class MockScheduler(BaseScheduler):
    """Mock scheduler for testing base functionality"""

    SCHEDULER_NAME = "mock"

    def get_status(self):
        return {"scheduler": "mock", "installed": False, "enabled": None, "interval": None}

    def is_installed(self):
        return False

    def install(self, interval, ddns_args=None):
        return True

    def uninstall(self):
        return True

    def enable(self):
        return True

    def disable(self):
        return True


class TestBaseScheduler(unittest.TestCase):
    """Test BaseScheduler functionality"""

    def setUp(self):
        """Set up test fixtures"""
        self.scheduler = MockScheduler()

    def test_scheduler_name_property(self):
        """Test scheduler name property"""
        self.assertEqual(self.scheduler.SCHEDULER_NAME, "mock")

    def test_abstract_methods_exist(self):
        """Test that all abstract methods are implemented"""
        required_methods = ["get_status", "is_installed", "install", "uninstall", "enable", "disable"]

        for method_name in required_methods:
            self.assertTrue(hasattr(self.scheduler, method_name))
            method = getattr(self.scheduler, method_name)
            self.assertTrue(callable(method))

    def test_build_ddns_command_basic(self):
        """Test _build_ddns_command with basic arguments"""
        ddns_args = {"dns": "debug", "ipv4": ["test.example.com"]}

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIsInstance(command, str)
        self.assertIn("python", command.lower())
        self.assertIn("ddns", command)
        self.assertIn("--dns", command)
        self.assertIn("debug", command)
        self.assertIn("--ipv4", command)
        self.assertIn("test.example.com", command)

    def test_build_ddns_command_with_config(self):
        """Test _build_ddns_command with config files"""
        ddns_args = {"dns": "cloudflare", "config": ["config1.json", "config2.json"]}

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIn("--config", command)
        self.assertIn("config1.json", command)
        self.assertIn("config2.json", command)

    def test_build_ddns_command_with_lists(self):
        """Test _build_ddns_command with list arguments"""
        ddns_args = {
            "dns": "debug",
            "ipv4": ["domain1.com", "domain2.com"],
            "ipv6": ["ipv6domain.com"],
            "proxy": ["http://proxy1:8080", "http://proxy2:8080"],
        }

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIn("domain1.com", command)
        self.assertIn("domain2.com", command)
        self.assertIn("ipv6domain.com", command)
        self.assertIn("http://proxy1:8080", command)

    def test_build_ddns_command_with_boolean_flags(self):
        """Test _build_ddns_command with boolean flags"""
        ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": True, "cache": True}

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIn("--debug true", command)
        self.assertIn("--cache true", command)

    def test_build_ddns_command_filters_debug_false(self):
        """Test _build_ddns_command filters out debug=False"""
        ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": False, "cache": True}  # This should be filtered out

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertNotIn("--debug false", command)
        self.assertIn("--cache true", command)

    def test_build_ddns_command_with_single_values(self):
        """Test _build_ddns_command with single value arguments"""
        ddns_args = {"dns": "alidns", "id": "test_id", "token": "test_token", "ttl": 600, "log_level": "INFO"}

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIn("--id", command)
        self.assertIn("test_id", command)
        self.assertIn("--token", command)
        self.assertIn("test_token", command)
        self.assertIn("--ttl", command)
        self.assertIn("600", command)

    def test_build_ddns_command_excludes_none_values(self):
        """Test _build_ddns_command behavior with None values"""
        ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ttl": None, "line": None}

        command = self.scheduler._build_ddns_command(ddns_args)

        # The current implementation includes None values as strings
        # This test verifies the actual behavior
        self.assertIn("--ttl", command)
        self.assertIn("None", command)
        self.assertIn("--line", command)

    def test_build_ddns_command_excludes_empty_lists(self):
        """Test _build_ddns_command excludes empty lists"""
        ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ipv6": [], "config": []}

        command = self.scheduler._build_ddns_command(ddns_args)

        # Should not include empty list arguments
        self.assertIn("--ipv4", command)
        self.assertNotIn("--ipv6", command)
        self.assertNotIn("--config", command)

    @patch("sys.executable", "/usr/bin/python3.9")
    def test_build_ddns_command_uses_current_python(self):
        """Test _build_ddns_command uses current Python executable"""
        ddns_args = {"dns": "debug", "ipv4": ["test.com"]}
        command = self.scheduler._build_ddns_command(ddns_args)

        # Should use sys.executable for Python path
        self.assertIn("python", command.lower())

    def test_build_ddns_command_with_special_characters(self):
        """Test _build_ddns_command handles special characters"""
        ddns_args = {"dns": "debug", "ipv4": ["test-domain.example.com"], "token": "test_token_with_special_chars!@#"}

        command = self.scheduler._build_ddns_command(ddns_args)

        self.assertIsInstance(command, str)
        self.assertIn("test-domain.example.com", command)
        self.assertIn("test_token_with_special_chars!@#", command)

    def test_all_scheduler_interface_methods(self):
        """Test that scheduler implements all interface methods correctly"""
        # Test get_status
        status = self.scheduler.get_status()
        self.assertIsInstance(status, dict)
        self.assertIn("scheduler", status)

        # Test is_installed
        installed = self.scheduler.is_installed()
        self.assertIsInstance(installed, bool)

        # Test install
        result = self.scheduler.install(5, {"dns": "debug"})
        self.assertIsInstance(result, bool)

        # Test uninstall
        result = self.scheduler.uninstall()
        self.assertIsInstance(result, bool)

        # Test enable
        result = self.scheduler.enable()
        self.assertIsInstance(result, bool)

        # Test disable
        result = self.scheduler.disable()
        self.assertIsInstance(result, bool)


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