"""Tests for signal handling neutrality.

AC Round 6 requirement: Verify SDK does not override existing OS signal handlers.
SDK must respect host application's lifecycle management (SIGTERM, SIGINT).
"""

import signal
import os
import pytest
from mca_sdk import MCAClient


class TestSignalHandlingNeutrality:
    """Test SDK does not interfere with OS signal handlers."""

    def test_sdk_does_not_override_sigterm_handler(self):
        """Test SDK initialization does not override existing SIGTERM handler.

        AC Round 6: If SDK overrides SIGTERM, it will block Kubernetes pod evictions.
        """
        # Register custom SIGTERM handler before SDK initialization
        custom_handler_called = []

        def custom_sigterm_handler(signum, frame):
            custom_handler_called.append(True)

        original_handler = signal.signal(signal.SIGTERM, custom_sigterm_handler)

        try:
            # Verify our handler is registered
            current_handler = signal.getsignal(signal.SIGTERM)
            assert (
                current_handler == custom_sigterm_handler
            ), "Custom handler should be registered before SDK init"

            # Initialize SDK
            client = MCAClient(
                service_name="signal-test",
                model_id="mdl-signal-001",
                team_name="test-team",
            )

            # CRITICAL: Verify SDK did NOT override our signal handler
            handler_after_init = signal.getsignal(signal.SIGTERM)
            assert (
                handler_after_init == custom_sigterm_handler
            ), "SDK must NOT override existing SIGTERM handler"

            client.shutdown()

        finally:
            # Restore original handler
            signal.signal(signal.SIGTERM, original_handler)

    def test_sdk_does_not_override_sigint_handler(self):
        """Test SDK initialization does not override existing SIGINT handler.

        AC Round 6: Preserves Ctrl+C / keyboard interrupt behavior.
        """
        custom_handler_called = []

        def custom_sigint_handler(signum, frame):
            custom_handler_called.append(True)

        original_handler = signal.signal(signal.SIGINT, custom_sigint_handler)

        try:
            current_handler = signal.getsignal(signal.SIGINT)
            assert current_handler == custom_sigint_handler

            # Initialize SDK
            client = MCAClient(
                service_name="signal-int-test",
                model_id="mdl-signal-002",
                team_name="test-team",
            )

            # Verify SDK did NOT override SIGINT
            handler_after_init = signal.getsignal(signal.SIGINT)
            assert (
                handler_after_init == custom_sigint_handler
            ), "SDK must NOT override existing SIGINT handler"

            client.shutdown()

        finally:
            signal.signal(signal.SIGINT, original_handler)

    @pytest.mark.skipif(os.name == "nt", reason="SIGHUP not available on Windows")
    def test_sdk_preserves_sighup_handler(self):
        """Test SDK does not interfere with SIGHUP (common in daemon processes)."""

        def custom_sighup_handler(signum, frame):
            pass

        original_handler = signal.signal(signal.SIGHUP, custom_sighup_handler)

        try:
            client = MCAClient(
                service_name="sighup-test",
                model_id="mdl-signal-003",
                team_name="test-team",
            )

            handler_after_init = signal.getsignal(signal.SIGHUP)
            assert (
                handler_after_init == custom_sighup_handler
            ), "SDK must NOT override SIGHUP handler"

            client.shutdown()

        finally:
            signal.signal(signal.SIGHUP, original_handler)

    def test_signal_handler_unchanged_after_telemetry_recording(self):
        """Test signal handlers remain unchanged during SDK operations."""

        def custom_handler(signum, frame):
            pass

        original_sigterm = signal.signal(signal.SIGTERM, custom_handler)

        try:
            client = MCAClient(
                service_name="telemetry-signal",
                model_id="mdl-signal-004",
                team_name="test-team",
            )

            # Record telemetry (activates background threads)
            for i in range(10):
                client.record_prediction(latency=0.1)

            # Verify handler still unchanged after telemetry operations
            current_handler = signal.getsignal(signal.SIGTERM)
            assert (
                current_handler == custom_handler
            ), "Signal handler should remain unchanged during telemetry operations"

            client.shutdown()

        finally:
            signal.signal(signal.SIGTERM, original_sigterm)

    def test_signal_handler_unchanged_after_shutdown(self):
        """Test signal handlers remain unchanged after SDK shutdown."""

        def custom_handler(signum, frame):
            pass

        original_sigterm = signal.signal(signal.SIGTERM, custom_handler)

        try:
            client = MCAClient(
                service_name="shutdown-signal",
                model_id="mdl-signal-005",
                team_name="test-team",
            )

            client.record_prediction(latency=0.1)
            client.shutdown()

            # Verify handler unchanged after shutdown
            current_handler = signal.getsignal(signal.SIGTERM)
            assert (
                current_handler == custom_handler
            ), "Signal handler should remain unchanged after SDK shutdown"

        finally:
            signal.signal(signal.SIGTERM, original_sigterm)

    def test_default_signal_handler_preserved(self):
        """Test SDK works correctly when default signal handlers are in place.

        Verifies SDK doesn't require custom handlers to function.
        """
        # Reset to default handlers
        original_sigterm = signal.signal(signal.SIGTERM, signal.SIG_DFL)
        original_sigint = signal.signal(signal.SIGINT, signal.SIG_DFL)

        try:
            client = MCAClient(
                service_name="default-signal",
                model_id="mdl-signal-006",
                team_name="test-team",
            )

            client.record_prediction(latency=0.1)

            # Verify still default after SDK init
            assert signal.getsignal(signal.SIGTERM) == signal.SIG_DFL
            assert signal.getsignal(signal.SIGINT) == signal.SIG_DFL

            client.shutdown()

        finally:
            signal.signal(signal.SIGTERM, original_sigterm)
            signal.signal(signal.SIGINT, original_sigint)
