#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <time.h>

// Инициализация дисплея с использованием аппаратного I2C
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

// Данные для подключения к Wi-Fi
const char* ssid = "Beeline_2G_A7F18A";
const char* password = "iD2tAXJN3e";

// Учетные данные для веб-сервера
const char* www_username = "admin";
const char* www_password = "35539900";

// Инициализация веб-сервера на порту 80
ESP8266WebServer server(80);

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

// Переменная для хранения времени будильника
String alarmTime = "";

// Определяем пин для светодиода
#define LED_PIN LED_BUILTIN  // Встроенный светодиод, обычно GPIO2 (D4)

// Определяем пин для зуммера
#define BUZZER_PIN 14  // GPIO14

// Переменные для управления миганием светодиода
unsigned long previousMillisLED = 0;
const long intervalLED = 1000;  // Интервал мигания в миллисекундах (1 секунда)
bool ledState = false;

// HTML-код для веб-страницы с отображением времени и даты (без изменений)
const char* htmlPage = R"=====(
<!DOCTYPE html>
<html>
<head>
  <title>Alarm Clock Settings</title>
  <style>
    body {
      background-color: #1E1E1E;
      color: #FFFFFF;
      font-family: Arial, sans-serif;
      text-align: center;
      padding-top: 50px;
    }
    h1 {
      color: #FF4081;
    }
    #time {
      font-size: 48px;
      margin: 20px 0;
    }
    #date {
      font-size: 32px;
      margin: 10px 0;
    }
    input[type=time] {
      padding: 10px;
      font-size: 18px;
      margin: 20px 0;
    }
    input[type=submit] {
      background-color: #FF4081;
      color: #FFFFFF;
      border: none;
      padding: 15px 30px;
      font-size: 18px;
      cursor: pointer;
    }
    input[type=submit]:hover {
      background-color: #E91E63;
    }
  </style>
</head>
<body>
  <h1>Alarm Clock</h1>
  <div id="time">--:--:--</div>
  <div id="date">--.--.----</div>
  <form action="/setAlarm" method="POST">
    <label for="alarm">Alarm Time:</label><br>
    <input type="time" id="alarm" name="alarm" required><br>
    <input type="submit" value="Set Alarm">
  </form>
  <script>
    function updateTime() {
      fetch('/time')
        .then(response => response.text())
        .then(dateTime => {
          let [time, date] = dateTime.split(' ');
          document.getElementById('time').textContent = time;
          document.getElementById('date').textContent = date;
        })
        .catch(err => console.error(err));
    }
    setInterval(updateTime, 1000); // Обновляем время каждую секунду
    updateTime(); // Обновляем сразу после загрузки страницы
  </script>
</body>
</html>
)=====";

void setup() {
  // Инициализация Serial Monitor
  Serial.begin(115200);

  // Инициализация I2C-шины
  Wire.begin();

  // Инициализация дисплея
  u8g2.begin();

  // Настраиваем пин для светодиода
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  // Выключаем светодиод (активный LOW)

  // Настраиваем пин для зуммера
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW); // Выключаем зуммер

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

  // Ожидание подключения
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nПодключено к Wi-Fi сети.");
  Serial.print("IP адрес: ");
  Serial.println(WiFi.localIP());

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

  // Настройка обработчиков для веб-сервера
  server.on("/", handleRoot);
  server.on("/setAlarm", HTTP_POST, handleSetAlarm);
  server.on("/time", handleTime); // Обработчик для отправки текущего времени и даты

  // Запуск веб-сервера
  server.begin();
  Serial.println("Веб-сервер запущен.");
}

void loop() {
  // Обновление времени через NTP
  timeClient.update();

  // Обработка запросов к веб-серверу
  server.handleClient();

  // Отображение текущего времени на дисплее
  displayTime();

  // Проверка будильника
  checkAlarm();

  // Мигание светодиода
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillisLED >= intervalLED) {
    previousMillisLED = currentMillis;
    // Инвертируем состояние светодиода
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState ? LOW : HIGH);  // Светодиод активен при LOW
  }
}

void displayTime() {
  // Получаем текущее время в секундах с 1 января 1970 года
  time_t rawTime = timeClient.getEpochTime();

  // Конвертируем в структуру tm
  struct tm * timeInfo = localtime(&rawTime);

  // Форматируем время и дату
  char timeString[9]; // "HH:MM:SS"
  char dateString[11]; // "DD.MM.YYYY"

  strftime(timeString, sizeof(timeString), "%H:%M:%S", timeInfo);
  strftime(dateString, sizeof(dateString), "%d.%m.%Y", timeInfo);

  // Отображение времени и даты на OLED-дисплее
  u8g2.clearBuffer();

  // Устанавливаем крупный шрифт для времени
  u8g2.setFont(u8g2_font_fub30_tr);  // Большой шрифт

  // Определяем ширину строки времени для центрирования
  int16_t timeWidth = u8g2.getStrWidth(timeString);
  int16_t timeX = (128 - timeWidth) / 2;  // 128 — ширина дисплея

  // Вывод времени по центру верхней части дисплея
  u8g2.drawStr(timeX, 35, timeString);

  // Устанавливаем более мелкий шрифт для даты
  u8g2.setFont(u8g2_font_ncenB14_tr);

  // Определяем ширину строки даты для центрирования
  int16_t dateWidth = u8g2.getStrWidth(dateString);
  int16_t dateX = (128 - dateWidth) / 2;

  // Вывод даты ниже времени
  u8g2.drawStr(dateX, 55, dateString);

  // Проверяем, установлен ли будильник
  if (alarmTime != "") {
    // Формируем строку с иконкой будильника и временем будильника
    String alarmDisplay = String("\xE2\x8F\xB0 ") + alarmTime;  // Используем символ Unicode для будильника

    // Преобразуем в char*
    char alarmString[16];
    alarmDisplay.toCharArray(alarmString, sizeof(alarmString));

    // Определяем ширину строки будильника для центрирования
    int16_t alarmWidth = u8g2.getStrWidth(alarmString);
    int16_t alarmX = (128 - alarmWidth) / 2;

    // Выводим время будильника ниже даты
    u8g2.drawStr(alarmX, 75, alarmString);
  }

  // Отправляем буфер на дисплей
  u8g2.sendBuffer();
}

void checkAlarm() {
  if (alarmTime != "") {
    time_t rawTime = timeClient.getEpochTime();
    struct tm * timeInfo = localtime(&rawTime);
    char currentTime[6]; // "HH:MM"
    strftime(currentTime, sizeof(currentTime), "%H:%M", timeInfo);

    if (String(currentTime) == alarmTime) {
      // Действие при срабатывании будильника
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.drawStr(10, 30, "ALARM!");
      u8g2.sendBuffer();

      // Включаем зуммер
      digitalWrite(BUZZER_PIN, HIGH);

      // Ждем 10 секунд (10000 миллисекунд)
      unsigned long buzzerStartTime = millis();
      while (millis() - buzzerStartTime < 10000) {
        // Обновляем веб-сервер и другие функции, чтобы устройство оставалось отзывчивым
        server.handleClient();
        timeClient.update();
        // Можно добавить код для остановки зуммера по действию пользователя
      }

      // Выключаем зуммер
      digitalWrite(BUZZER_PIN, LOW);

      // Сброс времени будильника
      alarmTime = "";
    }
  }
}

void handleRoot() {
  if(!server.authenticate(www_username, www_password)){
    return server.requestAuthentication();
  }
  server.send(200, "text/html", htmlPage);
}

void handleSetAlarm() {
  if(!server.authenticate(www_username, www_password)){
    return server.requestAuthentication();
  }

  if (server.hasArg("alarm")) {
    alarmTime = server.arg("alarm");
    Serial.print("Будильник установлен на: ");
    Serial.println(alarmTime);
    server.sendHeader("Location", "/");
    server.send(303);
  } else {
    server.send(400, "text/plain", "Bad Request");
  }
}

void handleTime() {
  if(!server.authenticate(www_username, www_password)){
    return server.requestAuthentication();
  }
  time_t rawTime = timeClient.getEpochTime();
  struct tm * timeInfo = localtime(&rawTime);

  char timeString[9]; // "HH:MM:SS"
  char dateString[11]; // "DD.MM.YYYY"

  strftime(timeString, sizeof(timeString), "%H:%M:%S", timeInfo);
  strftime(dateString, sizeof(dateString), "%d.%m.%Y", timeInfo);

  // Объединяем дату и время в одну строку
  String dateTimeString = String(timeString) + " " + String(dateString);

  server.send(200, "text/plain", dateTimeString);
} исправь код. нужно уменьшить строку времени так чтоб она не выдодила за границы дисплея , строку с датой сделай тонким шрифтом , ниже добавь время на которое установлен будильник и добавь рядом значек будильника