"""Test the core model classes."""

import pytest
from web_sentinel.model import ScanRequest, Finding, ScanResult


class TestScanRequest:
    """Test ScanRequest data model."""
    
    def test_scan_request_creation(self):
        """Test creating a ScanRequest with default values."""
        request = ScanRequest(domain="example.com")
        assert request.domain == "example.com"
        assert request.http_port == 80
        assert request.https_port == 443
        assert request.timeout == 5.0
        assert request.user_agent == "WebSentinel/1.0"
        assert request.allow_invasive is False
        assert request.source_path is None
        assert request.source_files == ()
        assert request.source_languages == ("auto",)
        assert request.source_exclude == ()
        assert request.source_recursive is True
        assert request.source_detailed_report is False
        assert request.source_min_severity == "medium"
        assert request.source_max_files == -1
        assert request.source_max_size_mb == -1
        assert request.source_advanced_rules is False
    
    def test_scan_request_custom_values(self):
        """Test creating a ScanRequest with custom values."""
        request = ScanRequest(
            domain="test.com",
            http_port=8080,
            https_port=8443,
            timeout=10.0,
            user_agent="Custom/1.0",
            allow_invasive=True
        )
        assert request.domain == "test.com"
        assert request.http_port == 8080
        assert request.https_port == 8443
        assert request.timeout == 10.0
        assert request.user_agent == "Custom/1.0"
        assert request.allow_invasive is True
    
    def test_scan_request_to_dict(self):
        """Test ScanRequest serialization to dictionary."""
        request = ScanRequest(domain="example.com", timeout=7.5)
        result = request.to_dict()
        
        expected = {
            "domain": "example.com",
            "http_port": 80,
            "https_port": 443,
            "timeout": 7.5,
            "user_agent": "WebSentinel/1.0",
            "allow_invasive": False,
            "source_languages": ["auto"],
            "source_recursive": True,
            "source_detailed_report": False,
            "source_min_severity": "medium",
            "source_max_files": -1,
            "source_max_size_mb": -1,
            "source_advanced_rules": False,
        }
        assert result == expected

    def test_scan_request_source_files_with_spaces(self):
        """Ensure Windows paths containing spaces stay intact."""
        request = ScanRequest(
            domain="example.com",
            source_files=("D:\\WEB API\\FailDaily\\file.py", "C:\\Temp\\other.js"),
        )
        assert request.source_files == (
            "D:\\WEB API\\FailDaily\\file.py",
            "C:\\Temp\\other.js",
        )


class TestFinding:
    """Test Finding data model."""
    
    def test_finding_creation_required_fields(self):
        """Test creating a Finding with only required fields."""
        finding = Finding(
            check="test",
            title="Test Issue",
            severity="medium",
            description="Test description",
            remediation="Fix the issue"
        )
        assert finding.check == "test"
        assert finding.title == "Test Issue"
        assert finding.severity == "medium"
        assert finding.description == "Test description"
        assert finding.remediation == "Fix the issue"
        assert finding.impact is None
        assert finding.evidence is None
    
    def test_finding_creation_all_fields(self):
        """Test creating a Finding with all fields."""
        finding = Finding(
            check="tls",
            title="SSL Certificate Expired",
            severity="high", 
            description="The SSL certificate has expired",
            remediation="Renew the certificate",
            impact="High security risk",
            evidence="Certificate expired on 2024-01-01"
        )
        assert finding.check == "tls"
        assert finding.title == "SSL Certificate Expired"
        assert finding.severity == "high"
        assert finding.description == "The SSL certificate has expired"
        assert finding.remediation == "Renew the certificate"
        assert finding.impact == "High security risk"
        assert finding.evidence == "Certificate expired on 2024-01-01"
    
    def test_finding_to_dict(self):
        """Test Finding serialization to dictionary."""
        finding = Finding(
            check="headers",
            title="Missing Header",
            severity="low",
            description="Security header missing",
            remediation="Add the header",
            impact="Low risk",
            evidence=None
        )
        result = finding.to_dict()
        
        expected = {
            "check": "headers",
            "title": "Missing Header", 
            "severity": "low",
            "description": "Security header missing",
            "remediation": "Add the header",
            "impact": "Low risk",
            "evidence": None
        }
        assert result == expected


class TestScanResult:
    """Test ScanResult data model."""
    
    def test_scan_result_creation(self, sample_scan_request, sample_finding):
        """Test creating a ScanResult."""
        result = ScanResult(
            request=sample_scan_request,
            findings=[sample_finding],
            started_at=None,
            finished_at=None
        )
        assert result.request == sample_scan_request
        assert len(result.findings) == 1
        assert result.findings[0] == sample_finding
    
    def test_scan_result_empty_findings(self, sample_scan_request):
        """Test creating a ScanResult with no findings."""
        result = ScanResult(request=sample_scan_request, findings=[])
        assert result.request == sample_scan_request
        assert len(result.findings) == 0
        assert result.findings == []
