// Project 12: ESP32 Telegram Bot (chat with your board)
// -----------------------------------------------------------------------------
// Talk to the ESP32 from the Telegram app on your phone, from anywhere:
//   /status     -> the board replies with the DHT11 temperature and humidity
//   /light_on   -> turns the LED (or relay) on
//   /light_off  -> turns it off
//   /help       -> lists the commands
// If you set CHAT_ID below, the board also PUSHES a message when the PIR sensor
// detects motion.
//
// It reuses parts you already know:
//   - DHT11 on GPIO 4      (Project 9)
//   - LED / relay on GPIO 26 (Projects 5 and 7)
//   - PIR on GPIO 27       (Project 4, optional, for motion alerts)
//
// Libraries (install from the Arduino Library Manager):
//   - "UniversalTelegramBot" (by Brian Lough)
//   - "ArduinoJson"          (by Benoit Blanchon, v6 or newer)
//   - "DHT sensor library" + "Adafruit Unified Sensor"
// -----------------------------------------------------------------------------

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

// ============================ EDIT THIS BLOCK ================================
const char *WIFI_SSID = "REPLACE_WITH_YOUR_SSID";
const char *WIFI_PASS = "REPLACE_WITH_YOUR_PASSWORD";

// From @BotFather in Telegram: create a bot, copy the HTTP API token.
#define BOT_TOKEN "REPLACE_WITH_YOUR_BOT_TOKEN"

// Optional: your personal chat id (from @userinfobot). Leave "" to disable the
// motion push. With an id set, the board messages you when the PIR trips.
#define CHAT_ID ""
// ============================================================================

#define DHTPIN   4
#define DHTTYPE  DHT11
#define LED_PIN  26
#define PIR_PIN  27

DHT dht(DHTPIN, DHTTYPE);

WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);

const unsigned long BOT_CHECK_INTERVAL = 1000;  // poll Telegram every 1 s
unsigned long lastBotCheck = 0;

bool lastMotion = false;

void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = bot.messages[i].chat_id;
    String text    = bot.messages[i].text;
    String from    = bot.messages[i].from_name;

    if (text == "/light_on") {
      digitalWrite(LED_PIN, HIGH);
      bot.sendMessage(chat_id, "Light is ON", "");
    }
    else if (text == "/light_off") {
      digitalWrite(LED_PIN, LOW);
      bot.sendMessage(chat_id, "Light is OFF", "");
    }
    else if (text == "/status") {
      float t = dht.readTemperature();
      float h = dht.readHumidity();
      String reply;
      if (isnan(t) || isnan(h)) {
        reply = "Sensor read failed, try again.";
      } else {
        reply  = "Temperature: " + String(t, 1) + " C\n";
        reply += "Humidity: " + String(h, 1) + " %\n";
        reply += "Light: " + String(digitalRead(LED_PIN) ? "ON" : "OFF");
      }
      bot.sendMessage(chat_id, reply, "");
    }
    else if (text == "/start" || text == "/help") {
      String reply = "Hi " + from + ", I am your ESP32.\n\n";
      reply += "/status - temperature, humidity, light state\n";
      reply += "/light_on - turn the light on\n";
      reply += "/light_off - turn the light off\n";
      reply += "/help - show this message";
      bot.sendMessage(chat_id, reply, "");
    }
    else {
      bot.sendMessage(chat_id, "Unknown command. Send /help.", "");
    }
  }
}

void setup() {
  Serial.begin(115200);
  delay(500);

  Serial.println();
  Serial.println("==============================================");
  Serial.println(" Project 12: ESP32 Telegram Bot");
  Serial.println("==============================================");

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  pinMode(PIR_PIN, INPUT);
  dht.begin();

  Serial.print("Connecting to Wi-Fi: ");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Wi-Fi connected!");

  // Telegram uses HTTPS. This root certificate lets the ESP32 trust it.
  secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT);

  Serial.println("Bot ready. Open Telegram and send /start to your bot.");
  Serial.println("----------------------------------------------");
}

void loop() {
  // Motion push (only if a CHAT_ID was set).
  bool motion = digitalRead(PIR_PIN);
  if (motion && !lastMotion && String(CHAT_ID).length() > 0) {
    bot.sendMessage(CHAT_ID, "Motion detected!", "");
    Serial.println("[PIR] motion -> alert sent");
  }
  lastMotion = motion;

  // Check for new Telegram messages on a timer (non-blocking style).
  if (millis() - lastBotCheck > BOT_CHECK_INTERVAL) {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    while (numNewMessages) {
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    lastBotCheck = millis();
  }
}
