// primitives_gallery — catalogo visual interactivo de los primitivos UI
// del registry (cpp/functions/core y cpp/functions/viz).
//
// Sidebar izquierdo con lista de primitivos agrupados por dominio; panel
// derecho renderiza la demo del item seleccionado (+ snippet de codigo).
//
// Rol: smoke test visual + documentacion viva + build gate en CI.
// NO se conecta a sqlite_api ni a ningun backend. Datos sinteticos.

#include "app_base.h"
#include "imgui.h"
#include "core/fullscreen_window.h"
#include "core/tokens.h"
#include "core/page_header.h"
#include "core/toast.h"
#include "core/app_menubar.h"
#include "gfx/gl_loader.h"

#include "demos.h"
#include "demo.h"

#include <cstdio>
#include <cstring>
#include <string>
#include <vector>

struct DemoEntry {
    const char* id;        // id estable, apto para comparar seleccion
    const char* label;     // texto en sidebar
    const char* category;  // "Core" o "Viz"
    void (*fn)();          // puntero a la demo_xxx
};

static const DemoEntry k_demos[] = {
    // Core
    {"button",          "button",          "Core", &gallery::demo_button},
    {"icon_button",     "icon_button",     "Core", &gallery::demo_icon_button},
    {"toolbar",         "toolbar",         "Core", &gallery::demo_toolbar},
    {"modal_dialog",    "modal_dialog",    "Core", &gallery::demo_modal},
    {"text_input",      "text_input",      "Core", &gallery::demo_text_input},
    {"select",          "select",          "Core", &gallery::demo_select},
    {"toast",           "toast + inbox",   "Core", &gallery::demo_toast},
    {"tree_view",       "tree_view",       "Core", &gallery::demo_tree_view},
    {"badge",           "badge",           "Core", &gallery::demo_badge},
    {"empty_state",     "empty_state",     "Core", &gallery::demo_empty_state},
    {"page_header",     "page_header",     "Core", &gallery::demo_page_header},
    {"dashboard_panel", "dashboard_panel", "Core", &gallery::demo_dashboard_panel},
    {"kpi_card",        "kpi_card",        "Core", &gallery::demo_kpi_card},
    {"text_editor",     "text_editor",     "Core", &gallery::demo_text_editor},     // wave 1
    {"file_watcher",    "file_watcher",    "Core", &gallery::demo_file_watcher},    // wave 1
    {"process_runner",  "process_runner",  "Core", &gallery::demo_process_runner},
    {"tween",           "tween_curves",    "Core", &gallery::demo_tween},
    {"bezier_editor",   "bezier_editor",   "Core", &gallery::demo_bezier_editor},
    {"timeline",        "timeline",        "Core", &gallery::demo_timeline},
    {"sql_workbench",   "sql_workbench",   "Core", &gallery::demo_sql_workbench},   // issue 0032
    // Viz
    {"bar_chart",       "bar_chart",       "Viz",  &gallery::demo_bar_chart},
    {"pie_chart",       "pie_chart",       "Viz",  &gallery::demo_pie_chart},
    {"line_plot",       "line_plot",       "Viz",  &gallery::demo_line_plot},
    {"scatter_plot",    "scatter_plot",    "Viz",  &gallery::demo_scatter_plot},
    {"histogram",       "histogram",       "Viz",  &gallery::demo_histogram},
    {"sparkline",       "sparkline",       "Viz",  &gallery::demo_sparkline},
    {"graph_viewport",  "graph_viewport",  "Viz",  &gallery::demo_graph},
    {"candlestick",     "candlestick",     "Viz",  &gallery::demo_candlestick},
    {"gauge",           "gauge",           "Viz",  &gallery::demo_gauge},
    {"heatmap",         "heatmap",         "Viz",  &gallery::demo_heatmap},
    {"table_view",      "table_view",      "Viz",  &gallery::demo_table_view},
    {"surface_plot_3d", "surface_plot_3d", "Viz",  &gallery::demo_surface_plot_3d},
    {"scatter_3d",      "scatter_3d",      "Viz",  &gallery::demo_scatter_3d},
    {"mesh_viewer",     "mesh_viewer",     "Viz",  &gallery::demo_mesh_viewer},
    {"treemap",         "treemap",         "Viz",  &gallery::demo_treemap},
    {"sankey",          "sankey",          "Viz",  &gallery::demo_sankey},
    {"chord",           "chord",           "Viz",  &gallery::demo_chord},
    {"contour",         "contour",         "Viz",  &gallery::demo_contour},
    {"voronoi",         "voronoi",         "Viz",  &gallery::demo_voronoi},
    // Gfx (shaders_lab core)
    {"shader_canvas",   "shader_canvas",   "Gfx",  &gallery::demo_shader_canvas},
    {"gl_texture",      "gl_texture_load", "Gfx",  &gallery::demo_gl_texture},      // wave 1
};
static constexpr int k_demo_count = sizeof(k_demos) / sizeof(k_demos[0]);

static std::string g_selected_id = "button";

static const DemoEntry* find_demo(const std::string& id) {
    for (int i = 0; i < k_demo_count; i++) {
        if (id == k_demos[i].id) return &k_demos[i];
    }
    return &k_demos[0];
}

static void draw_sidebar() {
    using namespace fn_tokens;
    ImGui::BeginChild("##gallery_sidebar", ImVec2(220, 0),
                      ImGuiChildFlags_Borders);

    const char* current_category = nullptr;
    for (int i = 0; i < k_demo_count; i++) {
        const auto& d = k_demos[i];
        if (!current_category || std::strcmp(current_category, d.category) != 0) {
            if (current_category) ImGui::Dummy(ImVec2(0, spacing::sm));
            ImGui::PushStyleColor(ImGuiCol_Text, colors::text_dim);
            ImGui::TextUnformatted(d.category);
            ImGui::PopStyleColor();
            ImGui::Separator();
            current_category = d.category;
        }

        const bool selected = (g_selected_id == d.id);
        ImGui::PushStyleColor(ImGuiCol_Header,        selected ? colors::surface_hover : ImVec4(0,0,0,0));
        ImGui::PushStyleColor(ImGuiCol_HeaderHovered, colors::surface_hover);
        ImGui::PushStyleColor(ImGuiCol_HeaderActive,  colors::surface);
        ImGui::PushStyleColor(ImGuiCol_Text,          selected ? colors::primary : colors::text);

        char label[96];
        std::snprintf(label, sizeof(label), "%s##sel_%s", d.label, d.id);
        if (ImGui::Selectable(label, selected)) {
            g_selected_id = d.id;
        }

        ImGui::PopStyleColor(4);
    }

    ImGui::EndChild();
}

static void render() {
    static bool init_done = false;
    if (!init_done) {
        fn_tokens::apply_dark_theme();
        // En Linux es no-op; en Windows resuelve los punteros GL via wglGetProcAddress.
        // Imprescindible antes de invocar primitivos que usen OpenGL 2.0+ (graph_viewport,
        // shader_canvas, etc).
        fn::gfx::gl_loader_init();
        init_done = true;
    }

    // MainMenuBar (solo Settings — la gallery no tiene paneles toggleables ni layouts)
    fn_ui::app_menubar(nullptr, 0, nullptr);

    fullscreen_window_begin("##gallery");

    page_header_begin("Primitives Gallery",
                      "Visual catalog of fn_registry C++ UI primitives");
    page_header_end();

    if (ImGui::BeginTable("##layout", 2,
            ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit)) {
        ImGui::TableSetupColumn("sidebar", ImGuiTableColumnFlags_WidthFixed,   220.0f);
        ImGui::TableSetupColumn("content", ImGuiTableColumnFlags_WidthStretch);
        ImGui::TableNextRow();

        ImGui::TableSetColumnIndex(0);
        draw_sidebar();

        ImGui::TableSetColumnIndex(1);
        ImGui::BeginChild("##gallery_content", ImVec2(0, 0),
                          ImGuiChildFlags_Borders,
                          ImGuiWindowFlags_HorizontalScrollbar);
        const DemoEntry* d = find_demo(g_selected_id);
        if (d && d->fn) d->fn();
        ImGui::EndChild();

        ImGui::EndTable();
    }

    fullscreen_window_end();

    // Toasts se renderizan encima para que el demo de toast funcione aqui tambien.
    fn_ui::toast_render();
}

int main(int /*argc*/, char** /*argv*/) {
    return fn::run_app(
        {.title = "fn_registry · Primitives Gallery",
         .width = 1400, .height = 900, .viewports = true},
        render
    );
}
