#pragma once
#include <cstdint>
#include "graph_types.h"

// Lectores de grafos para `GraphData` (issue 0049g). Disenado como un set de
// funciones con la misma firma `GraphLoadFn` para que anadir un backend nuevo
// (JSON, JSONL, GraphML, etc.) sea declarar otra funcion compatible — el
// resto del codigo (apps, viewport, force layout) no cambia.
//
// Esquema soportado de operations.db:
//   entities  (id, type_ref|type, name?, metadata?, updated_at)
//   relations (id, from_entity|source, to_entity|target, name?, type?,
//              weight?, updated_at)
// La funcion detecta los nombres reales via `PRAGMA table_info` y mapea:
//   - entity.type_ref / entity.type    → EntityType (color por hash de nombre)
//   - relation.name (o type)           → RelationType
//   - entity.id                        → user_data (FNV1a 64), label
//   - entity.metadata.name (json)      → label si existe, else id

namespace graph {

struct GraphLoadStats {
    int  nodes_loaded;
    int  edges_loaded;
    int  types_discovered;
    int  rel_types_discovered;
    int  errors;
    char error_msg[256];
};

// Firma uniforme para todos los backends. `uri` es opaco — para
// `graph_load_from_operations` es el path de un fichero SQLite.
typedef bool (*GraphLoadFn)(const char* uri, GraphData* out, GraphLoadStats* stats);

// Carga sincrona de operations.db. Allocs propios en out (nodes/edges/types/
// rel_types + string pool interno). El caller libera con graph_free.
bool graph_load_from_operations(const char* db_path, GraphData* out, GraphLoadStats* stats);

// Libera toda la memoria alocada por graph_load_from_operations (incluyendo
// los nombres de tipos y el label pool). Deja la struct a cero.
void graph_free(GraphData* graph);

// Devuelve el label de un nodo. Si label_idx == 0 o no hay pool, retorna "".
const char* graph_label(const GraphData* graph, uint32_t label_idx);

// --- Streaming --------------------------------------------------------------
// Pull-based: el caller invoca pull cada N ms y la fuente devuelve cuantas
// entidades/relaciones nuevas anadio in-place al GraphData. Si no hay sitio
// (capacity), corta y devuelve cuanto pudo escribir; el caller decide si
// reallocar.
struct GraphStreamSource;

GraphStreamSource* graph_stream_operations_open(const char* db_path, int poll_ms);
int                graph_stream_pull(GraphStreamSource* src, GraphData* graph);
void               graph_stream_close(GraphStreamSource* src);

} // namespace graph
