#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <windows.h>
#include "common/protocol.hpp"
#include <string>

// ==========================================================
// SharedMemoryManager v1.1
//  - Telemetry: Seqlock double-buffer (2 slot ping-pong).
//    Core ghi vào slot KHÔNG được publish, sau đó tăng
//    telemetrySequence (release). Agent đọc slot (seq & 1)
//    và kiểm tra lại sequence để phát hiện torn-read.
//  - Command: Hàng đợi vòng SPSC (Agent = producer duy nhất,
//    Core = consumer duy nhất) với 2 cursor nguyên tử.
//  - Watchdog: Nhịp tim 2 chiều qua lastCoreHeartbeat /
//    lastAgentHeartbeat (Unix ms).
// ==========================================================
class SharedMemoryManager {
public:
    enum class AgentWatchdogStatus {
        NoAgentEverConnected, // Agent chưa từng kết nối (chưa ghi nhịp tim)
        Healthy,              // Agent còn gửi nhịp tim định kỳ
        TimedOut              // Agent mất nhịp tim quá ngưỡng cho phép
    };

    SharedMemoryManager();
    ~SharedMemoryManager();

    // asServer = true : Core (Tier 1) tạo khối nhớ
    // asServer = false: Agent (Tier 2) mở khối nhớ có sẵn
    // mappingName     : cho phép override tên mapping (dùng trong unit test)
    bool Initialize(bool asServer = true, const char* mappingName = SHARED_MEM_NAME);
    void Shutdown();

    // ---- Telemetry (Core -> Agent) ----
    // Tier 1 (C++ Core): publish snapshot mới theo cơ chế Seqlock
    bool WriteTelemetry(const TelemetryPacket& packet);

    // Đọc snapshot mới nhất KHÔNG rách (tự động retry nếu writer đang ghi)
    bool ReadTelemetry(TelemetryPacket& outPacket, int maxRetries = 16) const;

    // ---- Command Ring SPSC (Agent -> Core) ----
    // Producer (Agent/Python): đẩy lệnh vào hàng đợi vòng. Trả về false nếu đầy.
    bool PublishCommand(const CommandPacket& cmd);

    // Consumer (Core): rút lệnh tiếp theo theo đúng thứ tự FIFO
    bool FetchNextCommand(CommandPacket& outCmd);

    // Số lệnh đang chờ trong hàng đợi
    uint64_t PendingCommandCount() const;

    // ---- Nhịp tim & Watchdog ----
    // Server cập nhật lastCoreHeartbeat, Client cập nhật lastAgentHeartbeat
    void UpdateHeartbeat();

    // Kiểm tra Agent còn sống hay không (chỉ có ý nghĩa ở phía Core/Server)
    AgentWatchdogStatus CheckAgentWatchdog(uint64_t timeoutMs) const;

    bool IsRunning() const;
    void RequestStop();

    bool IsServer() const { return m_isServer; }

    // Timestamp milliseconds hiện tại (Unix epoch)
    static uint64_t NowMs();

private:
    TelemetryPacket* SlotPtr(uint32_t slot) const;
    CommandPacket* CmdSlotPtr(uint64_t index) const;

    HANDLE m_hMapFile = nullptr;
    void* m_pView = nullptr;
    bool m_isServer = false;
    std::string m_name;

    SharedMemoryHeader* m_pHeader = nullptr;
};
