"""Test the orchestrator module loading system."""

import pytest
from web_sentinel.orchestrator import build_default_modules, CheckModule


class TestModuleLoading:
    """Test the module loading system."""
    
    def test_build_default_modules_basic(self):
        """Test that default modules can be built."""
        modules = build_default_modules()
        
        assert isinstance(modules, list)
        assert len(modules) >= 4  # At least core modules
        
        # Check that all returned items are CheckModule instances
        for module in modules:
            assert isinstance(module, CheckModule)
            assert hasattr(module, 'name')
            assert hasattr(module, 'description')
            assert hasattr(module, 'runner')
            assert hasattr(module, 'tags')
    
    def test_core_modules_present(self):
        """Test that core modules are always present."""
        modules = build_default_modules()
        module_names = [module.name for module in modules]
        
        # These modules should always be available
        assert "tls" in module_names
        assert "headers" in module_names
        assert "injection" in module_names
        assert "third-party" in module_names
    
    def test_static_analysis_module_optional(self):
        """Test that static-analysis module is handled gracefully."""
        modules = build_default_modules()
        module_names = [module.name for module in modules]
        
        # static-analysis may or may not be present depending on bs4 availability
        # This test just ensures the function doesn't crash
        if "static-analysis" in module_names:
            # If present, should have proper structure
            static_module = next(m for m in modules if m.name == "static-analysis")
            assert static_module.description
            assert static_module.runner
            assert "dom" in static_module.tags
        
        # Should have at least the core modules even if static-analysis is missing
        assert len(modules) >= 4
    
    def test_module_structure(self):
        """Test that each module has proper structure.""" 
        modules = build_default_modules()
        
        for module in modules:
            # Name should be non-empty string
            assert isinstance(module.name, str)
            assert len(module.name) > 0
            
            # Description should be non-empty string
            assert isinstance(module.description, str)
            assert len(module.description) > 0
            
            # Runner should be callable
            assert callable(module.runner)
            
            # Tags should be sequence
            assert hasattr(module.tags, '__iter__')
    
    def test_module_tags(self):
        """Test that modules have appropriate tags."""
        modules = build_default_modules()
        
        # Find TLS module and check its tags
        tls_module = next((m for m in modules if m.name == "tls"), None)
        assert tls_module is not None
        assert "passive" in tls_module.tags
        assert "network" in tls_module.tags
        
        # Find headers module and check its tags
        headers_module = next((m for m in modules if m.name == "headers"), None)
        assert headers_module is not None
        assert "passive" in headers_module.tags
        assert "http" in headers_module.tags
        
        # Find injection module and check its tags
        injection_module = next((m for m in modules if m.name == "injection"), None)
        assert injection_module is not None
        assert "active" in injection_module.tags
        assert "payloads" in injection_module.tags


class TestCheckModule:
    """Test the CheckModule dataclass."""
    
    def test_check_module_creation(self):
        """Test creating a CheckModule instance."""
        def dummy_runner(request):
            return []
        
        module = CheckModule(
            name="test-module",
            description="Test module description",
            runner=dummy_runner,
            tags=("test", "dummy")
        )
        
        assert module.name == "test-module"
        assert module.description == "Test module description"
        assert module.runner == dummy_runner
        assert module.tags == ("test", "dummy")
    
    def test_check_module_default_tags(self):
        """Test CheckModule with default empty tags."""
        def dummy_runner(request):
            return []
        
        module = CheckModule(
            name="test",
            description="Test",
            runner=dummy_runner
        )
        
        assert module.tags == ()
    
    def test_check_module_immutable(self):
        """Test that CheckModule is immutable (frozen dataclass)."""
        def dummy_runner(request):
            return []
        
        module = CheckModule(
            name="test",
            description="Test", 
            runner=dummy_runner
        )
        
        # Should not be able to modify frozen dataclass
        with pytest.raises(AttributeError):
            module.name = "modified"