#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <DHTesp.h>
#include <RTClib.h>
#include <TimeLib.h>
#include <NTPClient.h> 

// Define constants
const int BAUD_RATE = 9600;
const int DELAY_TIME = 1000;
const int SEND_DATA_INTERVAL = 10000;

// Define DHT sensor pins
const int DHT_PIN = 32;
const int DHT_VCC = 33;
const int DHT_GND = 34;

// Define LCD pins
const int LCD_ADDRESS = 0x27;
const int LCD_COLS = 20;
const int LCD_ROWS = 4;

// Create LCD object
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);

// Define the temperature ranges and corresponding messages
const int TEMP_NORMAL_MIN = 24;
const int TEMP_NORMAL_MAX = 29;
const int TEMP_WARNING_MIN = 30;
const int TEMP_WARNING_MAX = 34;
const int TEMP_CRITICAL_MIN = 35;
const int TEMP_CRITICAL_MAX = 100;
const char* TEMP_NORMAL_MSG = "Normal";
const char* TEMP_WARNING_MSG = "Warning";
const char* TEMP_CRITICAL_MSG = "Critical";

// WiFi credentials
const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASSWORD = " "; // Replace with your actual WiFi password

// Google Sheets API URL (Replace with your own)
const char* API_URL = "https://script.google.com/macros/s/AKfycbwR5mE-J4jD7ZtsPtnx-2gZYS9Jc--59ibe_e9oRSNJxbUPHBcEBKkcPC1-rRX8VROk/exec"; // Replace with your actual Google Sheets API URL

// Create instances for WiFi, HTTP client, DHT sensor, and RTC
DHTesp dht;
RTC_DS3231 rtc;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "my.pool.ntp.org", 0, 60000); 
HTTPClient http;

void setup() {
  Serial.begin(BAUD_RATE); 
  lcd.init();
  lcd.backlight(); 

  // DHT Setup
  pinMode(DHT_VCC, OUTPUT);
  digitalWrite(DHT_VCC, HIGH);
  pinMode(DHT_GND, OUTPUT);
  digitalWrite(DHT_GND, LOW);
  dht.setup(DHT_PIN, DHTesp::DHT22); 

  // WiFi Setup
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(DELAY_TIME);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // NTP Setup
  timeClient.begin();
  while (!timeClient.update()) {
    Serial.println("Waiting for NTP time sync...");
    delay(1000); 
  }
  Serial.println("NTP time synced!");

  // RTC Setup 
  rtc.begin();
  if (rtc.lostPower()) {
    Serial.println("RTC lost power. Enter current time (YYYY MM DD HH MM SS):");
    while (!Serial.available()) {
      delay(1); 
    }
    int year = Serial.parseInt();
    int month = Serial.parseInt();
    int day = Serial.parseInt();
    int hour = Serial.parseInt();
    int minute = Serial.parseInt();
    int second = Serial.parseInt();
  
    // Check for valid date and time data
    if (year < 2000 || year > 2100 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
      Serial.println("Invalid date and time. Please try again.");
    } else {
      rtc.adjust(DateTime(year, month, day, hour, minute, second));
      Serial.println ("RTC time set!");
    }
  } else {
    unsigned long epochTime = timeClient.getEpochTime();
    DateTime now(epochTime);
    rtc.adjust(now);
    Serial.println("RTC time set from NTP!"); 
  }
}

void displayTempHum(float temp, float hum, const char* notification) {
  lcd.clear();
  lcd.setCursor( 0, 0);
  lcd.print("Location 1");
  lcd.setCursor(0, 1);
  lcd.print("Temp: ");
  lcd.print(temp);
  lcd.print("C H:");
  lcd.print(hum);
  lcd.setCursor(0, 2); // Move to the third row
  lcd.print("Status: ");
  lcd.print(notification);
}

void sendToGoogleSheets(float temp, float hum, const char* notification, String date, String time) {
  String data = "{\"method\":\"append\",\"date\":\"" + date + "\",\"timestamp\":\"" + time + "\",\"temperature\":\"" + String(temp) + "\",\" humidity\":\"" + String(hum) + "\",\"notification\":\" " + notification + "\"}";

  // Send data to Google Sheets
  http.begin(API_URL);
  http.addHeader("Content-Type", "application/json");
  int httpCode = http.POST(data);

  if (httpCode > 0) {
    Serial.printf("HTTP response code: %d\n", httpCode);
    Serial.println("Data sent to Google Sheets successfully!");
  } else {
    Serial.printf("Error sending data to Google Sheets: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
}

void loop() {
  float temp = dht.getTemperature();
  float hum = dht.getHumidity();

  timeClient.update();
  unsigned long epochTime = timeClient.getEpochTime();
  DateTime now(epochTime);

  int year = now.year();
  int month = now.month();
  int day = now.day();

  String formattedDate = String(year) + "-" + String(month) + "-" + String(day);

  String formattedTime = timeClient.getFormattedTime();

  DateTime nowRTC = rtc.now(); // Rename now to nowRTC to avoid conflict

  // Extract date and time components
  int yearRTC = nowRTC.year();
  int monthRTC = nowRTC.month();
  int dayRTC = nowRTC.day();
  int hour = nowRTC.hour();
  int minute = nowRTC.minute();
  int second = nowRTC.second();

  // Create strings to display date and time
  String timeStr = String(hour) + ":" + String(minute) + ":" + String(second);

  String date = String(yearRTC) + "-" + String(monthRTC) + "-" + String(dayRTC); // Use yearRTC, monthRTC, and dayRTC here
  String time = timeStr;

  String notification;

  if (temp >= TEMP_NORMAL_MIN && temp <= TEMP_NORMAL_MAX) {
    notification = TEMP_NORMAL_MSG;
  } else if (temp >= TEMP_WARNING_MIN && temp <= TEMP_WARNING_MAX) {
    notification = TEMP_WARNING_MSG;
  } else if (temp >= TEMP_CRITICAL_MIN && temp <= TEMP_CRITICAL_MAX) {
    notification = TEMP_CRITICAL_MSG;
  }

  displayTempHum(temp, hum, notification.c_str());
  sendToGoogleSheets(temp, hum, notification.c_str(), formattedDate, formattedTime);

  delay(SEND_DATA_INTERVAL); 
}