// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
//
// lite_diagnostics.h — a small, thread-safe in-memory log of lite-wallet diagnostic events
// (server connection attempts, wallet open/create/restore, sync milestones, errors). Written
// from the controller's background threads and the App; read by the lite Console tab. Bounded
// so it can't grow without limit. Header-only (a Meyers singleton) so both the wallet layer
// and the UI can use it with no extra link target.

#pragma once

#include <chrono>
#include <cstdint>
#include <cstdio>
#include <ctime>
#include <deque>
#include <mutex>
#include <string>
#include <vector>

namespace dragonx {
namespace wallet {

class LiteDiagnostics {
public:
    // Defined in lite_diagnostics.cpp (a single TU) so there is exactly one instance across the
    // whole binary — no reliance on the linker folding an inline-function static across TUs.
    static LiteDiagnostics& instance();

    // Append a timestamped line (thread-safe). Safe to call from background threads.
    void log(const std::string& message) {
        std::string line = timestamp();
        line += message;
        std::lock_guard<std::mutex> lk(mutex_);
        lines_.push_back(std::move(line));
        if (lines_.size() > kMaxLines) lines_.pop_front();
        ++generation_;
    }

    // Copy of the current lines (oldest first).
    std::vector<std::string> snapshot() const {
        std::lock_guard<std::mutex> lk(mutex_);
        return std::vector<std::string>(lines_.begin(), lines_.end());
    }

    // Monotonic counter bumped on every change — lets readers re-snapshot only when it differs.
    std::uint64_t generation() const {
        std::lock_guard<std::mutex> lk(mutex_);
        return generation_;
    }

    void clear() {
        std::lock_guard<std::mutex> lk(mutex_);
        lines_.clear();
        ++generation_;
    }

private:
    LiteDiagnostics() = default;

    static std::string timestamp() {
        std::time_t t = std::time(nullptr);
        std::tm tmv{};
#ifdef _WIN32
        localtime_s(&tmv, &t);
#else
        localtime_r(&t, &tmv);
#endif
        char buf[16];
        std::snprintf(buf, sizeof(buf), "%02d:%02d:%02d  ", tmv.tm_hour, tmv.tm_min, tmv.tm_sec);
        return std::string(buf);
    }

    static constexpr std::size_t kMaxLines = 500;
    mutable std::mutex mutex_;
    std::deque<std::string> lines_;
    std::uint64_t generation_ = 0;
};

// Convenience: append a lite diagnostic line.
inline void liteLog(const std::string& message) { LiteDiagnostics::instance().log(message); }

}  // namespace wallet
}  // namespace dragonx
