"""
Tests basiques pour valider la structure et l'intégration des modules OWASP
"""

import pytest
from unittest.mock import Mock
import sys
from pathlib import Path

# Ajouter le répertoire racine au path
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

from web_sentinel.model import ScanRequest, Finding
from web_sentinel.checks.owasp_security_modules import (
    evaluate_access_control,
    evaluate_cryptographic_failures,
    evaluate_vulnerable_components,
    evaluate_insecure_design,
    evaluate_security_misconfiguration,
    evaluate_broken_authentication
)


class TestOWASPModulesBasic:
    """Tests basiques pour les modules OWASP."""
    
    @pytest.fixture
    def mock_scan_request(self):
        """Fixture pour une requête de scan simulée."""
        return ScanRequest(
            domain="example.com",
            timeout=10,
            allow_invasive=False
        )
    
    def test_access_control_module(self, mock_scan_request):
        """Test du module de contrôle d'accès."""
        findings = list(evaluate_access_control(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "access_control", "Check should be 'access_control'"
            assert hasattr(finding, 'title'), "Finding should have title"
            assert hasattr(finding, 'severity'), "Finding should have severity" 
            assert hasattr(finding, 'description'), "Finding should have description"
            assert hasattr(finding, 'remediation'), "Finding should have remediation"
    
    def test_crypto_failures_module(self, mock_scan_request):
        """Test du module de défaillances cryptographiques."""
        findings = list(evaluate_cryptographic_failures(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "crypto_failures", "Check should be 'crypto_failures'"
    
    def test_vulnerable_components_module(self, mock_scan_request):
        """Test du module de composants vulnérables."""
        findings = list(evaluate_vulnerable_components(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "vulnerable_components", "Check should be 'vulnerable_components'"
    
    def test_insecure_design_module(self, mock_scan_request):
        """Test du module de conception non sécurisée."""
        findings = list(evaluate_insecure_design(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "insecure_design", "Check should be 'insecure_design'"
    
    def test_security_misconfiguration_module(self, mock_scan_request):
        """Test du module de mauvaise configuration de sécurité.""" 
        findings = list(evaluate_security_misconfiguration(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "security_misconfiguration", "Check should be 'security_misconfiguration'"
    
    def test_broken_authentication_module(self, mock_scan_request):
        """Test du module d'authentification cassée."""
        findings = list(evaluate_broken_authentication(mock_scan_request))
        
        assert isinstance(findings, list), "Should return a list"
        assert len(findings) > 0, "Should return at least one finding"
        
        for finding in findings:
            assert isinstance(finding, Finding), "Should return Finding objects"
            assert finding.check == "broken_authentication", "Check should be 'broken_authentication'"
    
    def test_all_modules_return_valid_findings(self, mock_scan_request):
        """Test que tous les modules retournent des findings valides."""
        modules = [
            ("access_control", evaluate_access_control),
            ("crypto_failures", evaluate_cryptographic_failures),
            ("vulnerable_components", evaluate_vulnerable_components),
            ("insecure_design", evaluate_insecure_design),
            ("security_misconfiguration", evaluate_security_misconfiguration),
            ("broken_authentication", evaluate_broken_authentication)
        ]
        
        for module_name, module_func in modules:
            findings = list(module_func(mock_scan_request))
            
            # Vérifications basiques
            assert isinstance(findings, list), f"Module {module_name} should return a list"
            assert len(findings) > 0, f"Module {module_name} should return at least one finding"
            
            # Vérifications de la structure des findings
            for finding in findings:
                assert isinstance(finding, Finding), f"Module {module_name} should return Finding objects"
                assert finding.title, f"Module {module_name} finding should have non-empty title"
                assert finding.severity in ["critical", "high", "medium", "low", "info"], \
                    f"Module {module_name} finding should have valid severity"
                assert finding.description, f"Module {module_name} finding should have non-empty description"
                assert finding.remediation, f"Module {module_name} finding should have non-empty remediation"
    
    def test_scan_request_structure(self, mock_scan_request):
        """Test de la structure de ScanRequest."""
        assert hasattr(mock_scan_request, 'domain'), "ScanRequest should have domain attribute"
        assert hasattr(mock_scan_request, 'timeout'), "ScanRequest should have timeout attribute"
        assert hasattr(mock_scan_request, 'allow_invasive'), "ScanRequest should have allow_invasive attribute"
        
        assert mock_scan_request.domain == "example.com", "Domain should be set correctly"
        assert mock_scan_request.timeout == 10, "Timeout should be set correctly"
        assert mock_scan_request.allow_invasive == False, "Allow invasive should be set correctly"
    
    def test_finding_structure(self):
        """Test de la structure de Finding."""
        finding = Finding(
            check="test_check",
            title="Test Title",
            severity="medium",
            description="Test Description",
            remediation="Test Remediation"
        )
        
        assert finding.check == "test_check", "Check should be set correctly"
        assert finding.title == "Test Title", "Title should be set correctly"
        assert finding.severity == "medium", "Severity should be set correctly"
        assert finding.description == "Test Description", "Description should be set correctly" 
        assert finding.remediation == "Test Remediation", "Remediation should be set correctly"


if __name__ == "__main__":
    pytest.main([__file__, "-v"])