#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
// #include <ESP8266mDNS.h>    // Удалено
#include <ArduinoOTA.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Настройки Wi-Fi
const char* ssid     = "Beeline_2G_A7F18A";
const char* password = "iD2tAXJN3e";

// Настройки NTP
const long utcOffsetInSeconds = 3 * 3600; // Московское время (UTC+3)
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

// Настройки дисплея
#define SCREEN_WIDTH 128 // ширина OLED дисплея, в пикселях
#define SCREEN_HEIGHT 64 // высота OLED дисплея, в пикселях
#define OLED_RESET    -1 // сброс не используется
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Настройки сервера будильника
const char* alarmServerUrl = "http://yourserver.com/alarm";
int alarmHour = -1;
int alarmMinute = -1;

// Функции
void setupOTA() {
  ArduinoOTA.setHostname("ESP8266-AlarmClock");

  ArduinoOTA.onStart(OTA_onStart);
  ArduinoOTA.onEnd(OTA_onEnd);
  ArduinoOTA.onProgress(OTA_onProgress);
  ArduinoOTA.onError(OTA_onError);

  ArduinoOTA.begin();
}

// Определение обработчиков OTA
void OTA_onStart() {
  Serial.println("Начало OTA обновления");
}

void OTA_onEnd() {
  Serial.println("\nЗавершение OTA обновления");
}

void OTA_onProgress(unsigned int progress, unsigned int total) {
  Serial.printf("Прогресс: %u%%\r", (progress / (total / 100)));
}

void OTA_onError(ota_error_t error) {
  Serial.printf("Ошибка [%u]: ", error);
  if (error == OTA_AUTH_ERROR)
    Serial.println("Ошибка авторизации");
  else if (error == OTA_BEGIN_ERROR)
    Serial.println("Ошибка начала");
  else if (error == OTA_CONNECT_ERROR)
    Serial.println("Ошибка подключения");
  else if (error == OTA_RECEIVE_ERROR)
    Serial.println("Ошибка приёма");
  else if (error == OTA_END_ERROR)
    Serial.println("Ошибка завершения");
}

void fetchAlarmSettings() {
  WiFiClient client;
  HTTPClient http;
  http.begin(client, alarmServerUrl); // Обновлённый метод begin()

  int httpCode = http.GET();

  if (httpCode == HTTP_CODE_OK) {
    String payload = http.getString();

    // Разбор JSON
    StaticJsonDocument<200> doc;
    DeserializationError error = deserializeJson(doc, payload);

    if (!error) {
      alarmHour = doc["alarm_hour"];
      alarmMinute = doc["alarm_minute"];
      Serial.printf("Будильник установлен на %02d:%02d\n", alarmHour, alarmMinute);
    } else {
      Serial.println("Ошибка разбора JSON");
    }
  } else {
    Serial.printf("Ошибка подключения к серверу, код: %d\n", httpCode);
  }

  http.end();
}

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

  // Инициализация дисплея
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Адрес дисплея может быть 0x3C или 0x3D
    Serial.println(F("Не удалось найти OLED дисплей"));
    for (;;); // Остановимся здесь
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  // Подключение к Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  Serial.print("Подключение к Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nПодключено к сети Wi-Fi");

  // Запуск OTA
  setupOTA();

  // Запуск NTP клиента
  timeClient.begin();

  // Первоначальное получение настроек будильника
  fetchAlarmSettings();
}

void loop() {
  // Обработка OTA
  ArduinoOTA.handle();

  // Обновление времени
  timeClient.update();

  // Получение текущего времени
  int currentHour = timeClient.getHours();
  int currentMinute = timeClient.getMinutes();
  int currentSecond = timeClient.getSeconds();

  // Очистка дисплея
  display.clearDisplay();

  // Отображение времени на дисплее
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.printf("Time:\n%02d:%02d:%02d", currentHour, currentMinute, currentSecond);

  // Отображение будильника
  display.setTextSize(1);
  if (alarmHour >= 0 && alarmMinute >= 0) {
    display.setCursor(0, 40);
    display.printf("Alarm: %02d:%02d", alarmHour, alarmMinute);
  } else {
    display.setCursor(0, 40);
    display.print("Alarm: --:--");
  }

  // Обновление дисплея
  display.display();

  // Проверка срабатывания будильника
  if (currentHour == alarmHour && currentMinute == alarmMinute && currentSecond == 0) {
    Serial.println("Будильник сработал!");
    // Добавьте здесь код для действия будильника (например, звук или LED)
  }

  // Периодическое обновление настроек будильника каждые 60 секунд
  static unsigned long lastFetchTime = 0;
  if (millis() - lastFetchTime > 60000) {
    fetchAlarmSettings();
    lastFetchTime = millis();
  }

  delay(1000);
}