import paho.mqtt.client as mqtt
import queue
import logging
from typing import Any, Dict
import json

logger = logging.getLogger(__name__)

class MQTTBridge:
    def __init__(self, broker: str = "localhost", port: int = 1883):
        self._queues: Dict[str, queue.Queue] = {}
        self.broker = broker
        self.port = port
        self.client = mqtt.Client()
        self.client.on_message = self._on_message
        
        try:
            self.client.connect(self.broker, self.port, 60)
            self.client.loop_start()
            self.connected = True
        except Exception as e:
            logger.error(f"Failed to connect to MQTT broker: {e}")
            self.connected = False

    def _get_queue(self, topic: str) -> queue.Queue:
        if topic not in self._queues:
            self._queues[topic] = queue.Queue()
        return self._queues[topic]
        
    def _on_message(self, client, userdata, msg):
        try:
            payload = json.loads(msg.payload.decode())
            q = self._get_queue(msg.topic)
            q.put(payload)
        except Exception:
            pass

    def publish_action(self, topic: str, payload: Any) -> None:
        """Publishes an action payload to a specific MQTT topic."""
        logger.info(f"Publishing to {topic}: {payload}")
        if self.connected:
            self.client.publish(topic, json.dumps(payload))
        else:
            # Fallback to local queue if not connected to real broker
            q = self._get_queue(topic)
            q.put(payload)

    def subscribe_sensor(self, topic: str) -> queue.Queue:
        """Subscribes to a sensor topic and returns the queue for reading."""
        logger.info(f"Subscribing to {topic}")
        if self.connected:
            self.client.subscribe(topic)
        return self._get_queue(topic)
        
    def close(self):
        if self.connected:
            self.client.loop_stop()
            self.client.disconnect()
