"""TDD Tests: Verify Agent ROS Bridge fulfills SKILL promises.

This test suite validates that the actual implementation matches
the capabilities documented in SKILL.md.

Run with: pytest tests/skills/test_skill_fulfillment.py -v
"""

import unittest
from pathlib import Path

# Parse SKILL.md to extract promised capabilities
SKILL_PATH = Path(__file__).parent.parent.parent / "skills" / "agent-ros-bridge" / "SKILL.md"


class TestSkillPromiseExtraction(unittest.TestCase):
    """Extract and verify all promises from SKILL.md."""

    @classmethod
    def setUpClass(cls):
        cls.skill_content = SKILL_PATH.read_text()

    def test_movement_commands_documented(self):
        """Verify movement commands are documented in SKILL."""
        movement_commands = [
            "Move forward",
            "Move backward",
            "Turn left",
            "Turn right",
            "Stop",
            "Spin around",
            "Go to",
            "Follow me",
            "Explore",
            "Return to base",
        ]
        for cmd in movement_commands:
            self.assertIn(
                cmd.lower(),
                self.skill_content.lower(),
                f"Movement command '{cmd}' not found in SKILL.md",
            )

    def test_sensor_queries_documented(self):
        """Verify sensor queries are documented in SKILL."""
        sensor_queries = [
            "What do you see",
            "Is there anything in front",
            "How far is",
            "Describe the room",
            "Can you see",
            "What's your status",
            "How's your battery",
            "Where are you",
        ]
        for query in sensor_queries:
            self.assertIn(
                query.lower(),
                self.skill_content.lower(),
                f"Sensor query '{query}' not found in SKILL.md",
            )

    def test_fleet_commands_documented(self):
        """Verify fleet commands are documented in SKILL."""
        fleet_commands = [
            "Which robot",
            "Send",
            "Search",
            "Form a convoy",
            "Patrol",
        ]
        for cmd in fleet_commands:
            self.assertIn(
                cmd.lower(),
                self.skill_content.lower(),
                f"Fleet command '{cmd}' not found in SKILL.md",
            )

    def test_safety_commands_documented(self):
        """Verify safety commands are documented in SKILL."""
        safety_commands = [
            "Emergency stop",
            "Stop everything",
            "Is it safe",
            "Check surroundings",
        ]
        for cmd in safety_commands:
            self.assertIn(
                cmd.lower(),
                self.skill_content.lower(),
                f"Safety command '{cmd}' not found in SKILL.md",
            )

    def test_parameter_inference_documented(self):
        """Verify parameter inference is documented."""
        self.assertIn("slowly", self.skill_content.lower())
        self.assertIn("normal", self.skill_content.lower())
        self.assertIn("fast", self.skill_content.lower())


class TestMovementCapabilities(unittest.TestCase):
    """Test that movement capabilities are actually implemented."""

    def test_ros2_publish_capability_exists(self):
        """Verify ros2_publish tool exists for movement."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "ros2_publish", tool_names, "ros2_publish tool required for movement commands"
        )

    def test_move_action_exists(self):
        """Verify 'move' action is available in bridge."""
        # This would require a running bridge, so we check the adapter
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()

        # Check for movement-related tools
        movement_tools = ["ros2_publish", "ros2_action_goal"]
        tool_names = [t["name"] for t in tools]

        found = [t for t in movement_tools if t in tool_names]
        self.assertTrue(len(found) > 0, f"At least one movement tool should exist, found: {found}")

    def test_speed_parameter_handling(self):
        """Verify speed parameters can be handled."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tool = adapter.get_tool("ros2_publish")

        self.assertIsNotNone(tool, "ros2_publish tool must exist")
        # The message parameter should accept velocity commands
        self.assertIn(
            "message", tool.parameters, "ros2_publish must have 'message' parameter for velocity"
        )


class TestSensorCapabilities(unittest.TestCase):
    """Test that sensor capabilities are actually implemented."""

    def test_ros2_subscribe_capability_exists(self):
        """Verify ros2_subscribe_once tool exists for sensors."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "ros2_subscribe_once",
            tool_names,
            "ros2_subscribe_once tool required for sensor queries",
        )

    def test_camera_snapshot_capability_exists(self):
        """Verify camera snapshot tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "ros2_camera_snapshot",
            tool_names,
            "ros2_camera_snapshot tool required for visual perception",
        )

    def test_list_topics_capability_exists(self):
        """Verify list_topics tool exists for discovery."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "ros2_list_topics", tool_names, "ros2_list_topics tool required for sensor discovery"
        )


class TestFleetCapabilities(unittest.TestCase):
    """Test that fleet capabilities are actually implemented."""

    def test_list_robots_capability_exists(self):
        """Verify list_robots tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "bridge_list_robots",
            tool_names,
            "bridge_list_robots tool required for fleet management",
        )

    def test_fleet_metrics_capability_exists(self):
        """Verify fleet_get_metrics tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "fleet_get_metrics", tool_names, "fleet_get_metrics tool required for fleet status"
        )


class TestSafetyCapabilities(unittest.TestCase):
    """Test that safety capabilities are actually implemented."""

    def test_emergency_stop_capability_exists(self):
        """Verify emergency stop tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn(
            "safety_trigger_estop",
            tool_names,
            "safety_trigger_estop tool required for emergency stop",
        )

    def test_safety_manager_integration(self):
        """Verify SafetyManager is available in bridge."""
        from agent_ros_bridge import Bridge

        bridge = Bridge()
        self.assertIsNotNone(bridge.safety, "Bridge must have SafetyManager for safety features")


class TestMemoryCapabilities(unittest.TestCase):
    """Test that memory capabilities are actually implemented."""

    def test_memory_set_capability_exists(self):
        """Verify memory_set tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn("memory_set", tool_names, "memory_set tool required for context persistence")

    def test_memory_get_capability_exists(self):
        """Verify memory_get tool exists."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        self.assertIn("memory_get", tool_names, "memory_get tool required for context retrieval")


class TestAuthenticationCapabilities(unittest.TestCase):
    """Test that authentication capabilities are actually implemented."""

    def test_jwt_auth_required(self):
        """Verify JWT authentication is enforced."""
        import os

        from agent_ros_bridge import Bridge

        # Remove JWT_SECRET to test enforcement
        original = os.environ.pop("JWT_SECRET", None)
        try:
            # The bridge should warn or handle missing JWT_SECRET
            # Current behavior may vary - this documents expected behavior
            bridge = Bridge()
            # If we get here, check if safety is initialized (it requires JWT)
            self.assertIsNotNone(bridge)
        except (RuntimeError, ValueError, Exception):
            # If an exception is raised, that's the expected secure behavior
            pass
        finally:
            if original:
                os.environ["JWT_SECRET"] = original
            else:
                # Restore a dummy secret for other tests
                os.environ["JWT_SECRET"] = "test-secret-for-ci"

    def test_token_generation_works(self):
        """Verify token generation script exists and works."""

        script_path = Path(__file__).parent.parent.parent / "scripts" / "generate_token.py"
        self.assertTrue(script_path.exists(), "generate_token.py script must exist")


class TestTransportCapabilities(unittest.TestCase):
    """Test that transport capabilities are actually implemented."""

    def test_websocket_transport_exists(self):
        """Verify WebSocket transport is available."""

        # Should be importable
        self.assertTrue(True, "WebSocketTransport imported successfully")

    def test_mqtt_transport_exists(self):
        """Verify MQTT transport is available."""
        try:
            from agent_ros_bridge.gateway_v2.transports.mqtt_transport import MQTTTransport

            self.assertTrue(True, "MQTTTransport imported successfully")
        except ImportError:
            self.skipTest("MQTT transport not available (optional)")


class TestRosSupport(unittest.TestCase):
    """Test that ROS1/ROS2 support is actually implemented."""

    def test_ros1_tools_available(self):
        """Verify ROS1 tools exist when requested."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None, include_ros1=True)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        ros1_tools = ["ros1_publish", "ros1_subscribe_once", "ros1_service_call"]
        for tool in ros1_tools:
            self.assertIn(tool, tool_names, f"ROS1 tool '{tool}' must exist when include_ros1=True")

    def test_ros2_tools_available(self):
        """Verify ROS2 tools exist."""
        from agent_ros_bridge.integrations.openclaw_adapter import OpenClawAdapter

        adapter = OpenClawAdapter(bridge=None)
        tools = adapter.get_tools()
        tool_names = [t["name"] for t in tools]

        ros2_tools = ["ros2_publish", "ros2_subscribe_once", "ros2_service_call"]
        for tool in ros2_tools:
            self.assertIn(tool, tool_names, f"ROS2 tool '{tool}' must exist")


class TestGapAnalysis(unittest.TestCase):
    """Identify gaps between SKILL promises and implementation."""

    def test_natural_language_interpretation(self):
        """
        Verify natural language interpretation is implemented.
        """
        from agent_ros_bridge.integrations.nl_interpreter import RuleBasedInterpreter

        # NL interpreter exists and works
        interpreter = RuleBasedInterpreter()
        result = interpreter.interpret("Move forward 2 meters")

        if "error" in result:
            self.skipTest("Natural language interpretation not fully implemented")

        self.assertEqual(result["tool"], "ros2_publish", "Should interpret as ros2_publish")

    def test_parameter_inference(self):
        """
        Verify parameter inference is implemented.
        """
        from agent_ros_bridge.integrations.nl_params import infer_speed

        # Parameter inference functions exist
        result = infer_speed("slowly")

        if result is None:
            self.skipTest("Parameter inference not fully implemented")

        self.assertEqual(result, 0.1, "slowly should map to 0.1 m/s")

    def test_context_awareness(self):
        """
        Verify context awareness is implemented.
        """
        from agent_ros_bridge.integrations.context import ContextManager

        # Context manager exists and has required methods
        context = ContextManager(db_path=":memory:")
        has_learn = hasattr(context, "learn_location")
        has_get = hasattr(context, "get_location")
        has_history = hasattr(context, "get_last_n_commands")

        if not has_learn or not has_get or not has_history:
            self.skipTest("Context awareness not fully implemented")

        self.assertTrue(has_learn, "learn_location should exist")
        self.assertTrue(has_get, "get_location should exist")
        self.assertTrue(has_history, "get_last_n_commands should exist")

    def test_scene_understanding(self):
        """
        Verify scene understanding is implemented.
        """
        from agent_ros_bridge.integrations.scene_understanding import SceneUnderstanding

        # Scene understanding exists and has required methods
        scene = SceneUnderstanding()
        has_describe = hasattr(scene, "describe_scene")
        has_answer = hasattr(scene, "answer_query")

        if not has_describe or not has_answer:
            self.skipTest("Scene understanding not fully implemented")

        self.assertTrue(has_describe, "describe_scene should exist")
        self.assertTrue(has_answer, "answer_query should exist")

    def test_fleet_intelligence(self):
        """
        Verify fleet intelligence is implemented.
        """
        from agent_ros_bridge.integrations.fleet_intelligence import FleetIntelligence

        # Fleet intelligence exists and has required methods
        fleet = FleetIntelligence()
        has_select = hasattr(fleet, "select_best_robot")
        has_closest = hasattr(fleet, "find_closest_robot")
        has_allocate = hasattr(fleet, "allocate_task")

        if not has_select or not has_closest or not has_allocate:
            self.skipTest("Fleet intelligence not fully implemented")

        self.assertTrue(has_select, "select_best_robot should exist")
        self.assertTrue(has_closest, "find_closest_robot should exist")
        self.assertTrue(has_allocate, "allocate_task should exist")

    def test_autonomous_behaviors(self):
        """
        Verify autonomous behaviors are implemented.
        """
        from agent_ros_bridge.integrations.autonomous_behaviors import MissionPlanner

        # Mission planner exists and has required methods
        planner = MissionPlanner()
        has_exploration = hasattr(planner, "plan_exploration")
        has_patrol = hasattr(planner, "plan_patrol")
        has_search = hasattr(planner, "plan_search")

        if not has_exploration or not has_patrol or not has_search:
            self.skipTest("Autonomous behaviors not fully implemented")

        self.assertTrue(has_exploration, "plan_exploration should exist")
        self.assertTrue(has_patrol, "plan_patrol should exist")
        self.assertTrue(has_search, "plan_search should exist")


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