#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <time.h>

// WiFi credentials
const char* ssid = "XM";
const char* password = "79797979";

// Server URL for the PHP script
const char* serverUrl = "https://relaylog.nongnghiep24h.com/api/arduino_get_post/get_post_schedules_status.php";

// NTP Server
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 7 * 3600; // Adjust for your timezone (e.g., +7 hours for GMT+7)
const int   daylightOffset_sec = 0;

// Relay pins (adjust as needed for your relay board)
const int relayPins[] = {13, 12, 14, 27, 26}; // GPIO 13, 12, 14, 27, 26
const int numRelays = sizeof(relayPins) / sizeof(relayPins[0]);

void setup() {
    Serial.begin(115200);
    for (int i = 0; i < numRelays; i++) {
        pinMode(relayPins[i], OUTPUT);
        digitalWrite(relayPins[i], HIGH); // Relays OFF (assuming active low)
    }

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        // delay(500);
        Serial.print(".");
    }
    Serial.println("\nWiFi connected.");

    // Initialize and sync time
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    Serial.print("Time synchronized: ");
    printLocalTime();
}

void loop() {
    // Fetch schedules periodically (e.g., every minute)
    static unsigned long lastFetchTime = 0;
    if (millis() - lastFetchTime > 100) { // Fetch every 1/100 seconds
        fetchAndApplySchedules();
        lastFetchTime = millis();
    }
    
}

void printLocalTime() {
    struct tm timeinfo;
    if(!getLocalTime(&timeinfo)){
        Serial.println("Failed to obtain time");
        return;
    }
    Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}

void fetchAndApplySchedules() {
    if (WiFi.status() == WL_CONNECTED) {
        HTTPClient http;
        http.begin(serverUrl);
        int httpCode = http.GET();

        if (httpCode == HTTP_CODE_OK) {
            String payload = http.getString();
            Serial.println("Received payload: " + payload);
            
            JsonDocument doc;
            DeserializationError error = deserializeJson(doc, payload);

            if (!error) {
                JsonArray schedules = doc.as<JsonArray>();
                struct tm timeinfo;
                if(!getLocalTime(&timeinfo)){
                    Serial.println("Failed to obtain time for scheduling");
                    return;
                }
                
                int currentHour = timeinfo.tm_hour;
                int currentMin = timeinfo.tm_min;
                int currentDayOfWeek = timeinfo.tm_wday; // Sunday=0, Monday=1...

                for (JsonObject schedule : schedules) {
                    int relayId = schedule["relay_id"];
                    const char* targetTimeStr = schedule["selected_time"];
                    const char* daysOfWeek = schedule["selected_days"];
                    const char* state = schedule["status"];

                    // Parse target time (HH:MM:SS)
                    int targetHour, targetMin;
                    sscanf(targetTimeStr, "%d:%d", &targetHour, &targetMin);

                    // Check if current time matches target time (hourly/minutely check is sufficient)
                    if (currentHour == targetHour && currentMin == targetMin) {
                        // Check if current day of week is active
                        if (isDayActive(currentDayOfWeek, daysOfWeek)) {
                            // Control the relay
                            int pin = relayPins[relayId - 1]; // Assuming relay IDs start from 1
                            if (strcmp(state, "ON") == 0) {
                                sendRelayData(pin, state);
                                digitalWrite(pin, LOW); // Turn ON (adjust for your relay logic)
                                Serial.printf("Relay %d turned ON\n", relayId);
                            } else {
                                digitalWrite(pin, HIGH); // Turn OFF
                                Serial.printf("Relay %d turned OFF\n", relayId);
                            }
                        }
                    }
                }
            } else {
                Serial.print(F("deserializeJson() failed: "));
                Serial.println(error.f_str());
            }
        } else {
            Serial.printf("HTTP GET failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
    }
}

// Helper function to check if the current day is in the schedule string
bool isDayActive(int currentDay, const char* days) {
    // currentDayOfWeek: Sunday=0, Monday=1...
    // Days in DB: "Mon,Wed,Fri" or "All"
    if (strcmp(days, "All") == 0) return true;

    const char* dayNames[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    const char* currentDayName = dayNames[currentDay];

    return strstr(days, currentDayName) != nullptr;
}

//-------------
void sendRelayData(int relayId, String status) {
  HTTPClient http;
  http.begin(serverUrl);
  http.addHeader("Content-Type", "application/json");

  StaticJsonDocument<200> doc;
  doc["relay_id"] = relayId;
  doc["status"] = status;

  String jsonString;
  serializeJson(doc, jsonString);
  
  int httpResponseCode = http.POST(jsonString);
  http.end();
}


