#pragma once
//
// layout_storage — API publica de persistencia de layouts ImGui en SQLite.
//
// Ofrece un handle opaco (LayoutStorage*) para que las apps no tengan que
// gestionar sqlite3 ni el cableado save/load/list/delete contra el menu de
// layouts. Una app obtiene un LayoutCallbacks listo para pasarse a
// app_menubar() / layouts_menu_items() con dos llamadas:
//
//     auto* st = fn_ui::layout_storage_open("my_app.db");
//     fn_ui::LayoutCallbacks cb;
//     fn_ui::layout_storage_make_callbacks(st, cb);
//     // ...
//     fn_ui::layout_storage_close(st);
//
// Internamente:
//   * Tabla SQLite "imgui_layouts(name TEXT PRIMARY KEY, ini TEXT NOT NULL,
//     updated_at INTEGER NOT NULL)".
//   * save: serializa ImGui::SaveIniSettingsToMemory() y hace UPSERT por
//     nombre.
//   * load (on_apply): NO llama a ImGui::LoadIniSettingsFromMemory directo;
//     guarda el blob pendiente y lo aplica al inicio del proximo frame
//     (ver layout_storage_apply_pending).
//   * list: SELECT name FROM imgui_layouts ORDER BY updated_at DESC.
//   * remove: DELETE FROM imgui_layouts WHERE name = ?.
//
// La API es impure: hace I/O contra disco. Nunca lanza excepciones; en error
// las operaciones devuelven false / vector vacio / string vacia.

#include "core/layouts_menu.h"  // for fn_ui::LayoutCallbacks

namespace fn_ui {

struct LayoutStorage; // opaco — definido en layout_storage.cpp

// Abre (o crea) la BD en `db_path` y garantiza la tabla `imgui_layouts`.
// Retorna nullptr si no se puede abrir el fichero.
// El caller posee el handle y debe cerrarlo con layout_storage_close.
LayoutStorage* layout_storage_open(const char* db_path);

// Cierra la BD y libera el handle. Seguro con nullptr (no-op).
void layout_storage_close(LayoutStorage* s);

// Lista nombres de layouts guardados, ordenados por updated_at DESC (mas
// recientes primero). Retorna vector vacio en error o si s == nullptr.
std::vector<std::string> layout_storage_list(LayoutStorage* s);

// Guarda (UPSERT) un layout serializando ImGui::SaveIniSettingsToMemory().
// Debe llamarse desde un contexto con ImGui inicializado.
// Retorna true si la fila se inserto/actualizo, false en error.
bool layout_storage_save(LayoutStorage* s, const std::string& name);

// Marca un layout como "pendiente de aplicar". Carga el blob INI desde la BD
// pero NO llama a ImGui::LoadIniSettingsFromMemory todavia: aplicar settings
// dentro de un frame es inseguro, asi que se aplica en el proximo
// layout_storage_apply_pending.
// Retorna true si encontro el layout y quedo pendiente.
bool layout_storage_apply(LayoutStorage* s, const std::string& name);

// Aplica el blob pendiente (si lo hay) llamando a
// ImGui::LoadIniSettingsFromMemory. Llamar al INICIO del frame, antes de
// crear ventanas. No-op si no hay nada pendiente.
// Retorna el nombre del layout que se acaba de aplicar (vacio si no se
// aplico nada). Util para que la app actualice su `active_name`.
std::string layout_storage_apply_pending(LayoutStorage* s);

// Borra un layout por nombre. Retorna true si se borro al menos una fila.
bool layout_storage_delete(LayoutStorage* s, const std::string& name);

// Persiste el nombre del ultimo layout activo en la BD (tabla layout_meta,
// key='last_active'). Pasar string vacio limpia la entrada. Retorna true si
// la operacion completo. Idempotente.
bool layout_storage_set_last_active(LayoutStorage* s, const std::string& name);

// Lee el nombre del ultimo layout activo (o "" si no hay). Si el nombre
// almacenado ya no existe en imgui_layouts (porque se borro), retorna "".
std::string layout_storage_get_last_active(LayoutStorage* s);

// Rellena `out` con callbacks que envuelven este storage. Patron de uso:
//
//     auto* st = fn_ui::layout_storage_open("app.db");
//     fn_ui::LayoutCallbacks cb;
//     fn_ui::layout_storage_make_callbacks(st, cb);
//     // pasar cb a app_menubar() o layouts_menu_items() en cada frame
//     // y llamar fn_ui::layout_storage_apply_pending(st) al inicio del frame
//
// El handle `s` debe permanecer vivo durante toda la vida de los callbacks.
// `out.active_name` se actualiza automaticamente en on_save/on_apply/on_reset
// /on_delete.
void layout_storage_make_callbacks(LayoutStorage* s, LayoutCallbacks& out);

} // namespace fn_ui
