import random
import time
import paho.mqtt.client as mqtt
from pydantic import BaseModel
from typing import List

# Pydantic model for temperature data
class TemperatureData(BaseModel):
    sensor_name: str
    temperature: float

class TemperatureSensor:
    def __init__(self, sensor_name: str, mqtt_broker: str, mqtt_topic: str):
        self.sensor_name = sensor_name
        self.mqtt_broker = mqtt_broker
        self.mqtt_topic = mqtt_topic
        self.client = mqtt.Client()
        self.client.connect(mqtt_broker)
        self.client.loop_start()

    def publish_random_temperature(self):
        while True:
            temperature = random.uniform(-10, 30)
            data = TemperatureData(sensor_name=self.sensor_name, temperature=temperature)
            self.client.publish(self.mqtt_topic, data.json())
            time.sleep(1)

class MonitoringUnit:
    def __init__(self, mqtt_broker: str, mqtt_topic: str):
        self.mqtt_broker = mqtt_broker
        self.mqtt_topic = mqtt_topic
        self.client = mqtt.Client()
        self.client.on_message = self.on_message
        self.client.connect(mqtt_broker)
        self.client.subscribe(f"{mqtt_topic}/+") # + - single level wildcard
        self.client.loop_start()

    def on_message(self, client, userdata, message):
        payload = message.payload.decode('utf-8')
        try:
            data = TemperatureData.parse_raw(payload) 
            print(f"Received data from {data.sensor_name}: Temperature = {data.temperature}")
        except Exception as e:
            print(f"Failed to validate message: {str(e)}")

if __name__ == "__main__":
    # Start a monitoring unit that subscribes to all subtopics published on "sensors"
    monitoring_unit = MonitoringUnit(mqtt_broker="localhost", mqtt_topic="/sensors")
    # Start a temperature sensor that publishes to "/sensors/t1"
    t1_sensor = TemperatureSensor(sensor_name="t1", mqtt_broker="localhost", mqtt_topic="/sensors/t1")
    t1_sensor.publish_random_temperature()
