#ifndef MQTT_MANAGER_H
#define MQTT_MANAGER_H

#include "Arduino.h"
#include "config.h"
#include <PubSubClient.h>
#include <WiFi.h>
#include <cstddef>
#include <cstdint>

// MQTT Topics
#define MQTT_TOPIC_STATE "lumibot/%s/state"
#define MQTT_TOPIC_CONTROL "lumibot/%s/set"
#define MQTT_TOPIC_SET_POS "lumibot/%s/stepper/set_position"
#define MQTT_TOPIC_OPEN "lumibot/%s/stepper/open"
#define MQTT_TOPIC_CLOSE "lumibot/%s/stepper/close"
#define MQTT_TOPIC_CONFIG_SET "lumibot/%s/config/set"
#define MQTT_TOPIC_AVAIL "lumibot/%s/availability"
#define MQTT_TOPIC_DIAGNOSTICS "lumibot/%s/diagnostics"

// Connection settings
static constexpr unsigned long MQTT_RECONNECT_INTERVAL_MS = 5000;
static constexpr uint16_t MQTT_KEEPALIVE_SEC = 60;

// Buffer sizes:
// - STATE_BUFFER: Large (2048+512) for outgoing state JSON
// - MSG_BUFFER: For incoming control/config messages
#define MQTT_STATE_BUFFER_SIZE 4096
#define MQTT_MSG_BUFFER_SIZE 2048

class MqttManager {
public:
  MqttManager();

  void begin();
  void update();

  void publishState(bool force = false);
  void publishDiagnostics(bool verbose = false, bool reset = false);
  void publishLinkedDeviceMode(uint8_t mode);
  void publishLinkedDeviceSleepExit(); // FEAT-4: Exit bedtime via {"sleep": false}
  void processConfigCommand(const char *payload, unsigned int len);

  bool isConnected();
  bool isEnabled() const { return _enabled; }
  bool hasEverConnected() const { return _hasEverConnected; }
  const char* getDeviceId() const { return _deviceId; }

private:
  void connect();
  void handleMessage(char *topic, byte *payload, unsigned int length);
  void processControlCommand(const char *payload, unsigned int len);

  void generateDeviceId();

  WiFiClient _wifiClient;
  PubSubClient _mqttClient;

  char _deviceId[16];
  char _topicState[48];
  char _topicControl[48];
  char _topicSetPos[48];
  char _topicOpen[48];
  char _topicClose[48];
  char _topicConfigSet[80];
  char _topicAvail[80];
  char _topicDiag[80];
  char _topicLinkedDevice[80];

  // Single static buffer for all state publishing to prevent stack overflow
  // and heap fragmentation (moved from stack-allocated local variable).
  char _publishBuffer[MQTT_STATE_BUFFER_SIZE + 512];

  bool _enabled;
  bool _wasConnected;
  bool _hasEverConnected;
  unsigned long _lastConnectAttempt;
  unsigned long _lastStatePublish;
  unsigned long _reconnectDelay;
  static const unsigned long MAX_RECONNECT_DELAY = 60000;
};

extern MqttManager mqttManager;

#endif
