#include "viz/surface_plot_3d.h"

#include "imgui.h"
#include "implot3d.h"

#include <vector>

namespace fn {

void surface_plot_3d(const char* title, const SurfacePlot3DConfig& cfg) {
    if (!cfg.z || cfg.nx < 2 || cfg.ny < 2) {
        ImGui::BeginGroup();
        ImGui::TextDisabled("%s", title ? title : "##surface_plot_3d");
        ImGui::TextWrapped("surface_plot_3d: necesita z != nullptr y nx,ny >= 2 (recibido %dx%d)",
                           cfg.nx, cfg.ny);
        ImGui::EndGroup();
        return;
    }

    // Genera coordenadas X / Y por vertice (row-major, mismo layout que z).
    // ImPlot3D::PlotSurface espera arrays paralelos de nx*ny valores.
    const int total = cfg.nx * cfg.ny;
    std::vector<float> xs(total);
    std::vector<float> ys(total);
    const float dx = (cfg.nx > 1) ? (cfg.x_max - cfg.x_min) / float(cfg.nx - 1) : 0.f;
    const float dy = (cfg.ny > 1) ? (cfg.y_max - cfg.y_min) / float(cfg.ny - 1) : 0.f;
    for (int j = 0; j < cfg.ny; ++j) {
        const float y = cfg.y_min + dy * float(j);
        const int row = j * cfg.nx;
        for (int i = 0; i < cfg.nx; ++i) {
            xs[row + i] = cfg.x_min + dx * float(i);
            ys[row + i] = y;
        }
    }

    if (ImPlot3D::BeginPlot(title, cfg.size)) {
        ImPlot3D::SetupAxes(cfg.x_label, cfg.y_label, cfg.z_label);
        ImPlot3D::PlotSurface("##surface", xs.data(), ys.data(), cfg.z,
                              cfg.nx, cfg.ny);
        ImPlot3D::EndPlot();
    }

    if (cfg.show_colormap) {
        // ImPlot3D rinde su propia leyenda dentro del plot; el flag aqui se
        // reserva como contrato API por si en el futuro se necesita una
        // colormap-bar externa (no implementado todavia).
    }
}

} // namespace fn
