"""
Tests for cert_trust.core module
"""
import os
import sys
import tempfile
from pathlib import Path
from unittest.mock import patch, MagicMock

import pytest
from cert_trust import core


class TestSitePackages:
    """Test site-packages helper functions."""
    
    def test_site_packages_returns_list(self):
        """Should return a list of Path objects."""
        dirs = core._site_packages()
        assert isinstance(dirs, list)
        assert all(isinstance(d, Path) for d in dirs)
    
    def test_writable_site_packages_returns_path(self):
        """Should return a writable Path."""
        site_dir = core._writable_site_packages()
        assert site_dir is not None
        assert isinstance(site_dir, Path)
        # User site-packages should always be writable
        assert site_dir.exists() or site_dir.parent.exists()


class TestEnableDisable:
    """Test enable() and disable() functions."""
    
    def test_enable_creates_pth_file(self):
        """Enable should create a .pth file."""
        # Clean up any existing .pth files first
        core.disable()
        
        result = core.enable()
        
        assert result["success"] is True
        assert "pth_files" in result
        assert len(result["pth_files"]) > 0
        
        # Verify file exists
        pth_file = Path(result["pth_files"][0])
        assert pth_file.exists()
        assert pth_file.name == core.PTH_FILENAME
        
        # Clean up
        core.disable()
    
    def test_enable_idempotent(self):
        """Calling enable twice should be idempotent."""
        core.disable()  # Clean state
        
        result1 = core.enable()
        assert result1["success"] is True
        
        result2 = core.enable()
        assert result2["success"] is True
        assert result2["already_enabled"] is True
        
        # Clean up
        core.disable()
    
    def test_disable_removes_pth_file(self):
        """Disable should remove .pth files."""
        # First enable
        core.enable()
        
        # Then disable
        result = core.disable()
        
        assert result["success"] is True
        assert result["was_enabled"] is True
        assert len(result["removed"]) > 0
        
        # Verify file is gone
        assert core._existing_pth_files() == []
    
    def test_disable_when_not_enabled(self):
        """Disabling when not enabled should succeed gracefully."""
        core.disable()  # Ensure clean state
        
        result = core.disable()
        
        assert result["success"] is True
        assert result["was_enabled"] is False
        assert result["removed"] == []


class TestStatus:
    """Test status() function."""
    
    def test_status_returns_dict(self):
        """Status should return a properly structured dict."""
        result = core.status()
        
        assert isinstance(result, dict)
        assert "python" in result
        assert "curl" in result
        assert "platform" in result
        assert "python_version" in result
    
    def test_status_python_section(self):
        """Status should include Python trust information."""
        result = core.status()
        
        py = result["python"]
        assert "enabled" in py
        assert "env_disabled" in py
        assert "effective" in py
        assert "pth_files" in py
        assert "has_truststore" in py
        
        assert isinstance(py["enabled"], bool)
        assert isinstance(py["env_disabled"], bool)
        assert isinstance(py["pth_files"], list)
    
    def test_status_curl_section(self):
        """Status should include curl information."""
        result = core.status()
        
        curl = result["curl"]
        assert "available" in curl
        assert isinstance(curl["available"], bool)
        
        if curl["available"]:
            assert "ca_bundle" in curl
            assert "bundle_exists" in curl
            assert "uses_windows_store" in curl
    
    def test_status_reflects_enable_state(self):
        """Status should reflect enabled/disabled state."""
        core.disable()
        assert core.status()["python"]["enabled"] is False
        
        core.enable()
        assert core.status()["python"]["enabled"] is True
        
        core.disable()


class TestAddCert:
    """Test add_cert() function."""
    
    def test_add_cert_file_not_found(self):
        """Should fail gracefully when file doesn't exist."""
        result = core.add_cert("/nonexistent/file.crt")
        
        assert result["success"] is False
        assert "message" in result
        assert "not found" in result["message"].lower()
    
    def test_add_cert_invalid_extension(self):
        """Should reject files with invalid extensions."""
        with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as f:
            f.write(b"fake cert")
            temp_path = f.name
        
        try:
            result = core.add_cert(temp_path)
            assert result["success"] is False
            assert "format" in result["message"].lower()
        finally:
            os.unlink(temp_path)
    
    def test_add_cert_valid_extensions(self):
        """Should accept .crt, .pem, and .cer files."""
        # Create a fake certificate
        fake_cert = b"""-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKHHCgVZU5TOMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBnRl
c3RDQTAeFw0yMzAxMDEwMDAwMDBaFw0yNDAxMDEwMDAwMDBaMBExDzANBgNVBAMM
BnRlc3RDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1234567890
-----END CERTIFICATE-----
"""
        
        for ext in [".crt", ".pem", ".cer"]:
            with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as f:
                f.write(fake_cert)
                temp_path = f.name
            
            try:
                result = core.add_cert(temp_path)
                # May fail on permissions or missing dependencies, but should validate format
                assert "results" in result or "message" in result
            finally:
                os.unlink(temp_path)


class TestVerify:
    """Test verify() function."""
    
    def test_verify_returns_dict(self):
        """Verify should return a structured dict."""
        result = core.verify("https://www.google.com")
        
        assert isinstance(result, dict)
        assert "url" in result
        assert result["url"] == "https://www.google.com"
    
    def test_verify_includes_curl_result(self):
        """Should include curl test result if curl is available."""
        result = core.verify("https://www.google.com")
        
        if core.status()["curl"]["available"]:
            assert "curl" in result
            assert "success" in result["curl"]
    
    def test_verify_includes_python_result(self):
        """Should include Python SSL test result."""
        result = core.verify("https://www.google.com")
        
        assert "python" in result
        assert "success" in result["python"]
    
    @pytest.mark.integration
    def test_verify_valid_https_site(self):
        """Should successfully verify a valid HTTPS site."""
        result = core.verify("https://www.google.com")
        
        # At least one should succeed
        curl_ok = result.get("curl", {}).get("success", False)
        python_ok = result.get("python", {}).get("success", False)
        
        assert curl_ok or python_ok


class TestCurlHelpers:
    """Test curl helper functions."""
    
    def test_curl_ca_bundle_returns_path_or_none(self):
        """Should return a Path or None."""
        result = core._curl_ca_bundle()
        
        assert result is None or isinstance(result, Path)
    
    @pytest.mark.skipif(sys.platform == "win32", reason="Windows uses cert store")
    def test_curl_ca_bundle_on_linux_macos(self):
        """On Linux/macOS, should find a CA bundle if curl exists."""
        if core.status()["curl"]["available"]:
            result = core._curl_ca_bundle()
            # Should find a bundle path on Unix systems
            assert result is not None or sys.platform == "darwin"


class TestPlatformDetection:
    """Test platform-specific behavior."""
    
    def test_system_constant(self):
        """SYSTEM constant should be set correctly."""
        assert core.SYSTEM in ("Linux", "Darwin", "Windows")
        assert core.SYSTEM == os.uname().sysname if hasattr(os, 'uname') else "Windows"
    
    def test_pth_constants(self):
        """PTH constants should be defined."""
        assert core.PTH_FILENAME == "cert_trust_bootstrap.pth"
        assert core.PTH_CONTENT == "import cert_trust.bootstrap\n"


class TestEnvironmentVariables:
    """Test environment variable handling."""
    
    def test_status_respects_disable_env_var(self):
        """Status should check CERT_TRUST_DISABLED."""
        # Without env var
        with patch.dict(os.environ, {}, clear=False):
            os.environ.pop('CERT_TRUST_DISABLED', None)
            result = core.status()
            assert result["python"]["env_disabled"] is False
        
        # With env var
        with patch.dict(os.environ, {"CERT_TRUST_DISABLED": "1"}):
            result = core.status()
            assert result["python"]["env_disabled"] is True
    
    def test_effective_status_logic(self):
        """Effective status should be enabled AND NOT env_disabled."""
        core.enable()
        
        # Normal case: enabled and not env-disabled
        with patch.dict(os.environ, {}, clear=False):
            os.environ.pop('CERT_TRUST_DISABLED', None)
            result = core.status()
            assert result["python"]["effective"] is True
        
        # Env-disabled case
        with patch.dict(os.environ, {"CERT_TRUST_DISABLED": "1"}):
            result = core.status()
            assert result["python"]["effective"] is False
        
        core.disable()


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