#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <SD.h>
#include <SPI.h>

// Pin Definitions
#define DHT_PIN 27             
#define SOIL_MOISTURE_PIN 34  
#define LDR_PIN 35            
#define DHT_TYPE DHT22         
#define SD_CS_PIN 5           
#define SCK_PIN 18             
#define MISO_PIN 19            
#define MOSI_PIN 23            

// LCD Setup (I2C address 0x27, 16 columns, 2 rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);  

// ThingSpeak API
const char* ssid = "Wokwi-GUEST"; 
const char* password = "";
const char* apiKey = "MOM8Y14M2UKMYHEC";  
const char* server = "http://api.thingspeak.com";

// DHT Setup
DHT dht(DHT_PIN, DHT_TYPE);

// Timer for alternating display
unsigned long lastDisplayUpdate = 0;
int displayState = 0;  // 0 = Temp + Moisture, 1 = Light Level

void setup() {
  Serial.begin(115200);
  dht.begin();

  // Initialize LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");

  // Initialize SD Card
  Serial.println("Initializing SD card...");
  SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, SD_CS_PIN);  
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("SD Card initialization failed! Check wiring and SD card.");
    lcd.setCursor(0, 1);
    lcd.print("SD Init Failed!");
  } else {
    Serial.println("SD Card initialized successfully.");
    lcd.setCursor(0, 1);
    lcd.print("SD Ready!");
    delay(2000);
  }

  // Connect to Wi-Fi
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Connecting WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to Wi-Fi...");
  }
  Serial.println("Connected to Wi-Fi!");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("WiFi Connected");
  delay(2000);  
}

void loop() {
  // Read Sensor Values
  float temperature = dht.readTemperature();
    int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
  int lightLevel = analogRead(LDR_PIN);

  // Validate Sensor Readings
  if (isnan(temperature)) {
    Serial.println("Failed to read temperature from DHT sensor!");
    lcd.setCursor(0, 1);
    lcd.print("Temp Read Err!");
    return;
  }

  // Map Values to Percentage
  int soilMoisturePercent = map(soilMoistureValue, 500, 3000, 0, 100);
  soilMoisturePercent = constrain(soilMoisturePercent, 0, 100);
  int lightPercent = map(lightLevel, 0, 4095, 0, 100);

  // Print Readings to Serial Monitor
  Serial.println("Temperature: " + String(temperature) + " °C");
  Serial.println("Soil Moisture: " + String(soilMoisturePercent) + "%");
  Serial.println("Light Level: " + String(lightPercent) + "%");

  // Alternate LCD Display every 5 seconds
  if (millis() - lastDisplayUpdate > 5000) {
    lastDisplayUpdate = millis();
    if (displayState == 0) {
      // Show Temperature and Soil Moisture
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Temp: " + String(temperature) + "C");
      lcd.setCursor(0, 1);
      lcd.print("Moist: " + String(soilMoisturePercent) + "%");
      displayState = 1;  
    } else {
      // Show Light Level
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Light Level:");
      lcd.setCursor(0, 1);
      lcd.print(String(lightPercent) + "%");
      displayState = 0; 
    }
  }

  // Log Data to SD Card
  File dataFile = SD.open("/data.txt", FILE_APPEND);  
  if (dataFile) {
    dataFile.print("Temperature: ");
    dataFile.print(temperature);
    dataFile.print(" C, Soil Moisture: ");
    dataFile.print(soilMoisturePercent);
    dataFile.print("%, Light Level: ");
    dataFile.print(lightPercent);
    dataFile.println("%");
    dataFile.close();
    Serial.println("Data logged to SD card.");
  } else {
    Serial.println("Failed to write to SD card!");
    lcd.setCursor(0, 1);
    lcd.print("SD Write Fail!");
  }

  // Send Data to ThingSpeak
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = String(server) + "/update?api_key=" + apiKey +
                 "&field1=" + String(temperature) +
                 "&field2=" + String(soilMoisturePercent) +
                 "&field3=" + String(lightPercent);
    http.begin(url);
    int httpResponseCode = http.GET();
    if (httpResponseCode > 0) {
      Serial.println("Data sent to ThingSpeak!");
    } else {
      Serial.println("Failed to send data. Error: " + String(httpResponseCode));
    }
    http.end();
  } else {
    Serial.println("Wi-Fi disconnected!");
  }

  delay(15000);  
}