/*
 * ============================================================
 *  Ejemplo 09 — Notices en Tiempo Real (polling + repeticion)
 *
 *  Endpoint: GET /api/notices/{slug}
 *
 *  A diferencia del ejemplo 03 (fetch unico), este ejemplo
 *  hace polling continuo al endpoint de notices y soporta:
 *    - Deteccion automatica de nuevos envios (send_count)
 *    - Repetir el notice N veces con delay configurable
 *    - Duracion de display configurable desde el panel
 *    - Tipo de notificacion (info, success, warning, error, etc.)
 *
 *  Ideal para loaders/cheats con overlay ImGui donde quieres
 *  mostrar toasts/notificaciones en tiempo real.
 *
 *  Campos del JSON:
 *    message             — Texto del anuncio
 *    type                — "info" | "success" | "warning" | "error" | "none" | "config"
 *    is_active           — true si el anuncio esta activo
 *    display_duration_secs — Segundos que se muestra (0 = default 4s)
 *    repeat_times        — Cuantas veces repetir el notice
 *    repeat_delay_mins   — Minutos entre cada repeticion
 *    send_count          — Contador de envios (para detectar re-envios)
 * ============================================================
 */
#include <string>
#include <thread>
#include <chrono>
#include <unordered_map>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")

// ── Helper HTTP GET ──────────────────────────────────────────────────────────
std::string HttpGet(const std::string& url) {
    HINTERNET hInternet = InternetOpenA("SAO", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hInternet) return "";
    HINTERNET hUrl = InternetOpenUrlA(hInternet, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
    if (!hUrl) { InternetCloseHandle(hInternet); return ""; }
    std::string result;
    char buf[1024];
    DWORD read = 0;
    while (InternetReadFile(hUrl, buf, sizeof(buf), &read) && read > 0)
        result.append(buf, read);
    InternetCloseHandle(hUrl);
    InternetCloseHandle(hInternet);
    return result;
}

// ── Estado global del notice ─────────────────────────────────────────────────
std::string g_noticeMessage    = "";
std::string g_noticeType       = "info";
bool        g_noticeIsActive   = false;
bool        g_noticeLoaded     = false;
int         g_noticeDurationMs = 4000;
int         g_noticeRepeatTimes     = 1;
int         g_noticeRepeatDelayMins = 60;
int         g_noticeSendCount       = -1;   // -1 = no cargado aun

// ── Control de repeticion ────────────────────────────────────────────────────
int  s_nFired   = 1;       // Cuantas veces ya se mostro
bool s_nWaiting = false;   // Esperando el delay entre repeticiones
std::chrono::steady_clock::time_point s_nLastFired;

// ── Helpers para parsear JSON sin libreria externa ───────────────────────────
static std::string extractString(const std::string& json, const std::string& key) {
    std::string search = "\"" + key + "\":\"";
    auto pos = json.find(search);
    if (pos == std::string::npos) return "";
    pos += search.size();
    auto end = json.find("\"", pos);
    if (end == std::string::npos) return "";
    return json.substr(pos, end - pos);
}

static bool extractBool(const std::string& json, const std::string& key) {
    std::string search = "\"" + key + "\":";
    auto pos = json.find(search);
    if (pos == std::string::npos) return false;
    pos += search.size();
    return json.substr(pos, 4) == "true";
}

static int extractInt(const std::string& json, const std::string& key) {
    std::string search = "\"" + key + "\":";
    auto pos = json.find(search);
    if (pos == std::string::npos) return 0;
    pos += search.size();
    auto end = json.find_first_of(",}", pos);
    if (end == std::string::npos) return 0;
    try { return std::stoi(json.substr(pos, end - pos)); }
    catch (...) { return 0; }
}

// ── Thread de polling — corre en background ──────────────────────────────────
// Reemplaza "combo-anuncio" con el slug de tu notice en el panel
void FetchNotice() {
    while (true) {
        std::string json = HttpGet("https://saoauth.com/api/notices/combo-anuncio");

        if (!json.empty()) {
            int newSendCount = extractInt(json, "send_count");

            // Si el admin re-envio el notice (send_count subio), resetear repeticiones
            if (g_noticeSendCount != -1 && newSendCount > g_noticeSendCount) {
                s_nFired   = 0;
                s_nWaiting = false;
            }

            g_noticeSendCount       = newSendCount;
            g_noticeMessage         = extractString(json, "message");
            g_noticeType            = extractString(json, "type");
            g_noticeIsActive        = extractBool(json, "is_active");
            int secs                = extractInt(json, "display_duration_secs");
            g_noticeDurationMs      = (secs > 0) ? secs * 1000 : 4000;
            g_noticeRepeatTimes     = extractInt(json, "repeat_times");
            g_noticeRepeatDelayMins = extractInt(json, "repeat_delay_mins");
            g_noticeLoaded          = true;
        }

        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

// ── Ejemplo de uso en tu render loop (ImGui o similar) ───────────────────────
//
// En tu loop principal, despues de que g_noticeLoaded sea true:
//
//   if (g_noticeLoaded && g_noticeIsActive && !g_noticeMessage.empty()) {
//       bool canFire = false;
//
//       if (s_nFired == 0) {
//           canFire = true;  // Primera vez despues de un nuevo envio
//       }
//       else if (s_nFired < g_noticeRepeatTimes && s_nWaiting) {
//           auto elapsed = std::chrono::duration_cast<std::chrono::minutes>(
//               std::chrono::steady_clock::now() - s_nLastFired).count();
//           if (elapsed >= g_noticeRepeatDelayMins)
//               canFire = true;  // Ya paso el delay, repetir
//       }
//
//       if (canFire) {
//           // Mostrar tu toast/notificacion aqui
//           // Ejemplo con ImGui toast:
//           //   ImGui::NotificationFenix({ toastType, g_noticeDurationMs, g_noticeMessage.c_str() });
//
//           // Con MessageBox simple:
//           MessageBoxA(NULL, g_noticeMessage.c_str(), "Aviso", MB_ICONINFORMATION);
//
//           s_nLastFired = std::chrono::steady_clock::now();
//           s_nWaiting   = true;
//           s_nFired++;
//       }
//   }
//

int main() {
    // Lanzar thread de polling
    std::thread(FetchNotice).detach();

    // Esperar a que cargue el primer fetch
    while (!g_noticeLoaded) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    std::cout << "[Notice] Cargado correctamente\n";
    std::cout << "  Mensaje  : " << g_noticeMessage << "\n";
    std::cout << "  Tipo     : " << g_noticeType << "\n";
    std::cout << "  Activo   : " << (g_noticeIsActive ? "Si" : "No") << "\n";
    std::cout << "  Duracion : " << g_noticeDurationMs << " ms\n";
    std::cout << "  Repetir  : " << g_noticeRepeatTimes << " veces\n";
    std::cout << "  Delay    : " << g_noticeRepeatDelayMins << " min\n";

    // Simular render loop
    while (true) {
        if (g_noticeIsActive && !g_noticeMessage.empty()) {
            bool canFire = false;

            if (s_nFired == 0) {
                canFire = true;
            } else if (s_nFired < g_noticeRepeatTimes && s_nWaiting) {
                auto elapsed = std::chrono::duration_cast<std::chrono::minutes>(
                    std::chrono::steady_clock::now() - s_nLastFired).count();
                if (elapsed >= g_noticeRepeatDelayMins)
                    canFire = true;
            }

            if (canFire) {
                MessageBoxA(NULL, g_noticeMessage.c_str(), "Aviso en Tiempo Real", MB_ICONINFORMATION);
                s_nLastFired = std::chrono::steady_clock::now();
                s_nWaiting   = true;
                s_nFired++;
            }
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    return 0;
}
