import rclpy
from rclpy.action import ActionClient
from rclpy.node import Node
import json
from typing import Dict, Any
import logging

from drone_interfaces.action import ExecuteMission
from .websocket_manager import websocket_manager

class MissionActionClient(Node):
    """
    Interfaces with the drone's `ExecuteMission` ROS2 Action Server.
    """
    def __init__(self):
        super().__init__('mission_action_client')
        self._action_client = ActionClient(self, ExecuteMission, 'execute_mission')
        self.get_logger().info("MissionActionClient initialized.")

    def send_goal(self, py_tree: Dict[str, Any]):
        """
        Sends the mission (py_tree) to the action server.
        """
        if not self._action_client.server_is_ready():
            self.get_logger().error("Action server not available, goal not sent.")
            # Optionally, you could broadcast a status update to the frontend here
            return

        self.get_logger().info("Received request to send goal to drone.")
        goal_msg = ExecuteMission.Goal()
        goal_msg.py_tree_json = json.dumps(py_tree)

        self.get_logger().info(f"Sending goal to action server...")
        send_goal_future = self._action_client.send_goal_async(
            goal_msg,
            feedback_callback=self.feedback_callback
        )

        send_goal_future.add_done_callback(self.goal_response_callback)

    def goal_response_callback(self, future):
        goal_handle = future.result()
        if not goal_handle.accepted:
            self.get_logger().info('Goal rejected :(')
            return

        self.get_logger().info('Goal accepted :)')

        self._get_result_future = goal_handle.get_result_async()
        self._get_result_future.add_done_callback(self.get_result_callback)

    def get_result_callback(self, future):
        result = future.result().result
        self.get_logger().info(f'Result: {{success: {result.success}, message: {result.message}}}')
        # Optionally, you can broadcast the final result via WebSocket here

    def feedback_callback(self, feedback_msg):
        """
        This callback is triggered by the action server.
        It forwards the status to the QGC plugin via the WebSocket manager in a thread-safe manner.
        """
        feedback = feedback_msg.feedback
        feedback_payload = json.dumps({"node_id": feedback.node_id, "status": feedback.status})
        self.get_logger().info(f"Received feedback: {feedback_payload}")
        websocket_manager.broadcast(feedback_payload)

# Note: The rclpy.init() and spinning of the node will be handled in main.py
