import unittest
import ssl

# Assuming security.encrypt is accessible in the Python path
# If not, adjust the import based on project structure (e.g., using relative imports)
try:
    from security.encrypt import create_tls_context
except ImportError:
    # Handle cases where the module might be run directly or path issues
    import sys
    import os
    # Add the project root to the path if necessary
    # sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
    # from security.encrypt import create_tls_context
    # This might require more robust path handling depending on the test runner setup
    print("Warning: Could not import 'security.encrypt'. Ensure PYTHONPATH is set correctly.")
    # As a fallback for simple cases, try importing directly if tests are run from root
    try:
        from encrypt import create_tls_context
    except ImportError:
         raise ImportError("Failed to import create_tls_context from security.encrypt")


class TestTlsConfig(unittest.TestCase):

    def test_client_context_requires_tls1_3(self):
        """Verify client context minimum version is TLS 1.3"""
        context = create_tls_context(purpose=ssl.Purpose.CLIENT_AUTH)
        self.assertEqual(context.minimum_version, ssl.TLSVersion.TLSv1_3,
                         "Client context should require TLS 1.3")
        # Check that older protocols are implicitly disabled by setting minimum_version
        self.assertTrue(context.options & ssl.OP_NO_TLSv1_2, "TLS 1.2 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_TLSv1_1, "TLS 1.1 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_TLSv1, "TLS 1.0 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_SSLv3, "SSLv3 should be disabled")


    def test_server_context_requires_tls1_3(self):
        """Verify server context minimum version is TLS 1.3"""
        context = create_tls_context(purpose=ssl.Purpose.SERVER_AUTH)
        self.assertEqual(context.minimum_version, ssl.TLSVersion.TLSv1_3,
                         "Server context should require TLS 1.3")
        # Check that older protocols are implicitly disabled by setting minimum_version
        self.assertTrue(context.options & ssl.OP_NO_TLSv1_2, "TLS 1.2 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_TLSv1_1, "TLS 1.1 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_TLSv1, "TLS 1.0 should be disabled")
        self.assertTrue(context.options & ssl.OP_NO_SSLv3, "SSLv3 should be disabled")

# --- Negative Test Cases ---

    def test_server_rejects_tls1_2_client(self):
        """Verify server context rejects connection attempts using only TLS 1.2"""
        server_context = create_tls_context(purpose=ssl.Purpose.CLIENT_AUTH)
        # NOTE: Requires setting up a test server and client socket pair.
        # The client context should be configured to ONLY allow TLS 1.2:
        # client_context_tls12 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        # client_context_tls12.maximum_version = ssl.TLSVersion.TLSv1_2
        # client_context_tls12.minimum_version = ssl.TLSVersion.TLSv1_2 # Force TLS 1.2
        # ... setup sockets, wrap them, attempt handshake ...
        with self.assertRaises(ssl.SSLError, msg="Server should reject TLS 1.2 connection"):
            # Placeholder for actual handshake attempt simulation
            # e.g., client_socket.do_handshake()
            # In a real test, replace the following line with actual socket/handshake code
            raise ssl.SSLError("Simulated handshake failure for TLS 1.2") # Simulate failure

    def test_client_rejects_tls1_2_server(self):
        """Verify client context rejects connection attempts to a TLS 1.2 server"""
        client_context = create_tls_context(purpose=ssl.Purpose.SERVER_AUTH)
        # NOTE: Requires setting up a test server and client socket pair.
        # The server context should be configured to ONLY allow TLS 1.2:
        # server_context_tls12 = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        # server_context_tls12.maximum_version = ssl.TLSVersion.TLSv1_2
        # server_context_tls12.minimum_version = ssl.TLSVersion.TLSv1_2 # Force TLS 1.2
        # ... setup sockets, wrap them, attempt handshake ...
        with self.assertRaises(ssl.SSLError, msg="Client should reject connection to TLS 1.2 server"):
            # Placeholder for actual handshake attempt simulation
            # e.g., client_socket.do_handshake()
            # In a real test, replace the following line with actual socket/handshake code
            raise ssl.SSLError("Simulated handshake failure for TLS 1.2") # Simulate failure

    # Add similar tests for TLS 1.1, TLS 1.0, SSLv3 if deemed necessary,
    # although rejecting TLS 1.2 often covers the older ones implicitly.
    # Add more tests here if specific ciphers, cert loading, or other options were configured
    # For example:
    # def test_specific_cipher_suite_enabled(self):
    #     context = create_tls_context()
    #     enabled_ciphers = [cipher['name'] for cipher in context.get_ciphers()]
    #     self.assertIn('EXPECTED-CIPHER-SUITE-NAME', enabled_ciphers)


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