#include <HTTPClient.h>   // omogućava slanje HTTP zahtjeva (POST/GET)
#include <WiFi.h>         // WiFi konekcija za ESP32
#include "DHT.h"          // biblioteka za DHT senzor
#include "time.h"         // rad sa vremenom preko interneta (NTP)

// WiFi podaci za konekciju
const char* ssid = "IOT_PR6";
const char* password = "iotIV1proba";


// URL tvoje PHP skripte koja prima podatke i ubacuje u bazu
const char* serverUrl = "https://a13.etsbi.freeddns.org/mensurmehic/upisp.php";

// Definicija DHT senzora
#define DHTPIN 4          // pin na ESP32 gdje je spojen senzor
#define DHTTYPE DHT11     // tip senzora (DHT11)
DHT dht(DHTPIN, DHTTYPE); // kreiranje objekta senzora

// NTP server za dobijanje tačnog vremena
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;   // osnovna vremenska zona (GMT+1 za BiH)
const int daylightOffset_sec = 3600;  // dodatni +1 sat zbog ljetnog računanja vremena (ukupno GMT+2)

// Funkcija za povezivanje na WiFi
void initWiFi() {
  WiFi.mode(WIFI_STA); // ESP32 radi kao klijent (spaja se na router)
  WiFi.begin(ssid, password); // pokreće konekciju

  Serial.print("Konektujem se na WiFi ..");

  // petlja dok se ne spoji (blokira dalje izvršavanje)
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nWiFi povezan!");
  Serial.print("IP adresa: ");
  Serial.println(WiFi.localIP()); // ispis IP-a koji je dobio od routera
}

// Funkcija koja vraća trenutno vrijeme kao string
String getFormattedTime() {
  struct tm timeinfo;

  // pokušaj uzeti vrijeme sa NTP servera
  if(!getLocalTime(&timeinfo)){
    return "N/A"; // ako ne uspije (nema neta ili sync fail)
  }

  char buffer[20];

  // formatiranje vremena u čitljiv oblik (YYYY-MM-DD HH:MM:SS)
  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &timeinfo);

  return String(buffer); // pretvara u Arduino String
}

void setup() {
  Serial.begin(115200); // pokretanje Serial Monitora
  dht.begin();          // inicijalizacija DHT senzora

  initWiFi();           // poziv funkcije za WiFi konekciju

  // pokretanje NTP sinkronizacije vremena
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  struct tm timeinfo;
  Serial.println("Čekam NTP vrijeme...");

  // čeka dok ne dobije validno vrijeme (blokira dok ne uspije)
  while(!getLocalTime(&timeinfo)){
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nVrijeme sinkronizirano!");

  // TESTNI zahtjev da provjeri da li server radi
  HTTPClient http;
  http.begin(serverUrl); // otvara konekciju prema URL-u

  // header kaže serveru da šaljemo form-data (kao HTML forma)
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");

  int httpCode = http.POST("test=1");  // šalje dummy podatak

  if (httpCode > 0) {
    Serial.print("Server HTTP kod: ");
    Serial.println(httpCode); // npr 200 = uspjeh
  } else {
    Serial.print("Greška HTTP: ");
    Serial.println(http.errorToString(httpCode)); // opis greške
  }

  http.end(); // zatvara konekciju (obavezno)
}

void loop() {
  // čitanje podataka sa senzora
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();

  // provjera da li je očitanje validno (NaN = greška)
  if (isnan(temp) || isnan(hum)) {
    Serial.println("Greška pri očitanju senzora!");
    delay(2000);
    return; // preskače ostatak loop-a i pokušava opet
  }

  // uzimanje trenutnog vremena
  String vrijeme = getFormattedTime();

  // ispis podataka u Serial Monitor (za debug)
  Serial.println("\n==============================");
  Serial.print("Temperatura: ");
  Serial.println(temp);

  Serial.print("Vlažnost: ");
  Serial.println(hum);

  Serial.print("Vrijeme mjerenja: ");
  Serial.println(vrijeme);

  // SLANJE PODATAKA NA SERVER
  if (WiFi.status() == WL_CONNECTED) {

    HTTPClient http;
    http.begin(serverUrl); // priprema konekciju

    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    // formiranje POST stringa koji PHP prima preko $_POST
    String postData = "temperatura=" + String(temp) + "&vlaznost=" + String(hum);

    int httpCode = http.POST(postData); // slanje podataka

    if(httpCode > 0) {
      Serial.print("Podaci poslani, HTTP kod: ");
      Serial.println(httpCode);
    } else {
      Serial.print("Greška pri slanju podataka: ");
      Serial.println(http.errorToString(httpCode));
    }

    http.end(); // zatvara konekciju
  } else {
    Serial.println("WiFi nije povezan!");
  }

  delay(180000); // pauza 3 minute (da ne spamuje server)
}