// sse_client.h — Server-Sent Events C++ client with reconnect + Last-Event-ID.
//
// Background-thread client that reads a text/event-stream via curl -N (no
// buffer). Parses SSE spec fields, fires per-event and status callbacks, and
// reconnects with exponential backoff when the server closes.
//
// No link-time libcurl required — requires only `curl` in PATH at runtime.
// Same transport strategy as http_request_cpp_core and llm_anthropic_cpp_core.
#pragma once

#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <thread>

namespace fn_sse {

// A single parsed SSE event per the W3C spec.
struct Event {
    std::string event;    // "message" if no "event:" field was present
    std::string data;     // "data:" lines joined with "\n"; trailing "\n" stripped
    std::string id;       // last "id:" seen (used as Last-Event-ID on reconnect)
    int         retry_ms = 0;  // from "retry:" field, 0 if absent
};

struct Config {
    std::string url;
    std::string bearer_token;               // optional: Authorization: Bearer <token>
    int         connect_timeout_ms  = 5000; // curl --connect-timeout
    int         reconnect_initial_ms = 1000;
    int         reconnect_max_ms    = 30000; // exponential backoff cap
    bool        auto_reconnect      = true;
};

// Asynchronous SSE client.  Call start() once; the background thread loops
// reading the stream and invoking callbacks.  Call stop() to tear down.
//
// Thread safety: on_event / on_status are called from the background thread.
// If they touch UI state, callers must protect with their own mutex.
class Client {
public:
    using EventHandler  = std::function<void(const Event&)>;
    // status strings: "connecting" | "connected" | "disconnected" | "error: <msg>"
    using StatusHandler = std::function<void(const std::string&)>;

    Client();
    ~Client();

    // Start the background thread.  Idempotent — no-op if already running.
    void start(const Config& cfg,
               EventHandler  on_event,
               StatusHandler on_status = nullptr);

    // Signal the thread to stop and join.  Safe to call multiple times.
    void stop();

    bool is_running() const;

private:
    struct Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace fn_sse
