import paho.mqtt.client as mqtt
import os
import time

# --- Configuration ---
MQTT_BROKER_HOST = os.getenv("MQTT_BROKER_HOST", "localhost") # Should match producer's target broker
MQTT_BROKER_PORT = int(os.getenv("MQTT_BROKER_PORT", 1883))
MQTT_CLIENT_ID = os.getenv("MQTT_SUBSCRIBER_CLIENT_ID", "my_mac_subscriber")
MQTT_USER = os.getenv("MQTT_USER") # Set if your broker requires auth
MQTT_PASS = os.getenv("MQTT_PASS") # Set if your broker requires auth
SUBSCRIBE_TOPIC = os.getenv("SUBSCRIBE_TOPIC", "client_status/simple_will_tester/will")

# --- MQTT Callbacks ---
def on_connect(client, userdata, flags, rc, properties=None): # properties for v5, rc for v3.1.1/v5
    if rc == 0:
        print(f"Subscriber connected successfully to broker (rc={rc})")
        # Subscribing in on_connect() means that if we lose the connection and
        # reconnect then subscriptions will be renewed.
        client.subscribe(SUBSCRIBE_TOPIC, qos=1)
        print(f"Subscribed to topic: {SUBSCRIBE_TOPIC}")
    else:
        print(f"Subscriber connection failed with result code {rc}")
        if rc == 5: # MQRC_NOT_AUTHORIZED (common for username/password issues)
            print("Connection refused: Not authorized. Check username/password if broker requires them.")

def on_message(client, userdata, msg):
    print(f"Received message on topic '{msg.topic}': {msg.payload.decode()}")

def on_disconnect(client, userdata, rc, properties=None): # properties for v5
    if rc != 0:
        print(f"Subscriber unexpectedly disconnected (rc={rc}). Will attempt to reconnect if loop_forever is used and broker is back.")
    else:
        print("Subscriber disconnected gracefully.")

def on_subscribe(client, userdata, mid, granted_qos, properties=None): # properties for v5
    print(f"Subscribed with MID {mid}, Granted QoS: {granted_qos}")


# --- MQTT Client Setup ---
# Use CallbackAPIVersion.VERSION2 for the newer callback signatures like on_connect taking 'properties'
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=MQTT_CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.on_subscribe = on_subscribe # Optional: for feedback on subscription

if MQTT_USER and MQTT_PASS:
    client.username_pw_set(username=MQTT_USER, password=MQTT_PASS)

print(f"Subscriber attempting to connect to MQTT Broker: {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}")
try:
    client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT, 60) # 60-second keepalive
except ConnectionRefusedError as e:
    print(f"Connection refused: {e}. Check if broker is running and accessible, and credentials if used.")
    exit(1)
except OSError as e: # Catches "Network is unreachable" or similar
    print(f"OS error connecting: {e}. Check network and broker address.")
    exit(1)
except Exception as e:
    print(f"Error connecting to MQTT Broker: {e}")
    exit(1)

# client.loop_start() # Use this if you need to do other things in your main thread
# while True:
#     time.sleep(1) # Example for loop_start()
# client.loop_stop()

client.loop_forever() # Blocks execution and processes network traffic, callbacks, and reconnections.
