#pragma once
//
// agent_runs_timeline.h — ImGui panel: cross-app timeline of agent runs.
//
// API surface declared per issue 0118. Render is impure (uses ImGui); pure
// helpers live in agent_runs_timeline_helpers.{h,cpp} so unit tests can
// exercise filter / sort / formatting without a GL context.
//
// Typical wiring (consumer side):
//
//   fn_viz::TimelineState g_state;
//   g_state.sse_url = "http://127.0.0.1:8497/api/runs/stream";
//   g_state.on_select = [](const std::string& id){ open_detail_panel(id); };
//
//   ImGui::Begin("Agent runs");
//   fn_viz::render_agent_runs_timeline(g_state);
//   ImGui::End();
//
//   // Whenever a worker thread (real SSE client, polling fallback, fixture)
//   // wants to update the list:
//   {
//     std::lock_guard<std::mutex> lk(g_state.runs_mutex);
//     g_state.runs = new_runs;
//     g_state.connection_status = "connected";
//   }
//
// SSE client itself is OUT OF SCOPE for this issue — see the documented stub
// in poll_sse_runs() and the .md ## Gotchas section.

#include <cstdint>
#include <functional>
#include <mutex>
#include <string>
#include <vector>

namespace fn_viz {

struct AgentRun {
    std::string id;
    std::string app;              // kanban_cpp | skill_tree | ...
    std::string issue_id;
    std::string card_id;
    std::string branch;
    std::string status;           // pending|running|done|validated|merged|aborted|failed
    int64_t     started_at = 0;   // unix epoch seconds
    int64_t     finished_at = 0;  // 0 if still running
    int         dod_total = 0;
    int         dod_done = 0;
    int         dod_validated = 0;
};

struct TimelineFilter {
    std::vector<std::string> apps;
    std::vector<std::string> statuses;
    int64_t since_ts = 0;         // 0 means "no lower bound"
};

struct TimelineState {
    std::string sse_url;
    std::vector<AgentRun> runs;
    TimelineFilter filter;
    std::function<void(const std::string& run_id)> on_select;
    std::string selected_run_id;
    std::string connection_status;   // "connected"|"disconnected"|"connecting"
    std::mutex  runs_mutex;          // SSE thread writes, UI reads
};

// Renders the timeline INLINE inside the current ImGui window. The caller
// owns ImGui::Begin/End — this function only draws filters, badge, table
// and footer counts. Safe to call every frame; cost is O(N) over runs.
void render_agent_runs_timeline(TimelineState& state);

// STUB. Documented in agent_runs_timeline.md ## Gotchas.
// Today this is a no-op. The intent is that a future issue wires either:
//   (a) a real SSE client (libcurl multi + custom read callback), or
//   (b) a polling fallback that calls fn_core::http_request("GET", url, ...)
//       every N seconds and replaces state.runs under runs_mutex.
// Until then, the consumer is responsible for populating state.runs (e.g.
// test fixtures, or an in-process orchestrator that owns the data already).
void poll_sse_runs(TimelineState& state);

}  // namespace fn_viz
