#include <Adafruit_Sensor.h>
#include <DHT_U.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32Servo.h>
#include <FastLED.h>

#define DHTPIN 12
#define LED 26
#define SERVO_PIN 2
#define LED_PIN 4
#define NUM_LEDS 16
#define DHTTYPE DHT22

DHT_Unified dht(DHTPIN, DHTTYPE);
Servo servo;
CRGB leds[NUM_LEDS];

const char* ssid = "Wokwi-GUEST";
const char* mqttServer = "broker.hivemq.com";
const char* clientID = "esp32client123";
const char* topic = "Tempdata";

WiFiClient espClient;
PubSubClient client(espClient);

float temp = 0, hum = 0;
bool ledState = false;
unsigned long prevRead = 0, lastMsg = 0;

void setup_wifi() {
  WiFi.begin(ssid);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.println("\nWiFi connected");
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect(clientID)) {
      client.subscribe("lights");
      client.subscribe("servo");
      client.subscribe("lights/neopixel");
    } else {
      delay(5000);
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  String data = String((char*)payload).substring(0, length);
  if (strcmp(topic, "lights") == 0)
    digitalWrite(LED, data == "ON" ? HIGH : LOW);
  else if (strcmp(topic, "servo") == 0)
    servo.write(data.toInt());
  else if (strcmp(topic, "lights/neopixel") == 0) {
    int r, g, b;
    sscanf(data.c_str(), "%d,%d,%d", &r, &g, &b);
    fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
    FastLED.show();
  }
}

void readSensor() {
  sensors_event_t t, h;
  dht.temperature().getEvent(&t);
  dht.humidity().getEvent(&h);
  if (!isnan(t.temperature)) temp = t.temperature;
  if (!isnan(h.relative_humidity)) hum = h.relative_humidity;
}

void publishData() {
  String msg = String(temp) + "," + String(hum);
  client.publish(topic, msg.c_str());
  client.publish("/ThinkIOT/temp", String(temp, 2).c_str());
  client.publish("/ThinkIOT/hum", String(hum, 1).c_str());
}

void controlServoAndLED() {
  servo.write(temp < 30 ? 0 : 90);
  ledState = !ledState;
  digitalWrite(LED, ledState);
  delay(temp < 30 ? 20 : 10);
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  pinMode(LED, OUTPUT);
  servo.attach(SERVO_PIN, 500, 2400);
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  setup_wifi();
  client.setServer(mqttServer, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) reconnect();
  client.loop();

  unsigned long now = millis();

  if (now - prevRead >= 1000) {
    prevRead = now;
    readSensor();
    publishData();
    controlServoAndLED();
  }
}