// Unit tests for graph_force_layout_should_pause — el helper puro que el
// caller usa para decidir si parar la simulacion tras N frames consecutivos
// con energia < umbral. La logica del contador es responsabilidad del caller;
// la funcion solo decide "ya cumple" en base al contador y al umbral.

#define CATCH_CONFIG_MAIN
#include "catch_amalgamated.hpp"

#include "viz/graph_force_layout.h"

TEST_CASE("should_pause requires consecutive frames over threshold", "[viz][pause]") {
    const int min_consec = 30;

    REQUIRE_FALSE(graph_force_layout_should_pause(0,  min_consec));
    REQUIRE_FALSE(graph_force_layout_should_pause(1,  min_consec));
    REQUIRE_FALSE(graph_force_layout_should_pause(29, min_consec));
    REQUIRE      (graph_force_layout_should_pause(30, min_consec));
    REQUIRE      (graph_force_layout_should_pause(31, min_consec));
    REQUIRE      (graph_force_layout_should_pause(1000, min_consec));
}

TEST_CASE("should_pause with min_consecutive=0 always pauses", "[viz][pause]") {
    // Edge case: si el caller pide 0 frames, considerar siempre convergido.
    REQUIRE(graph_force_layout_should_pause(0, 0));
    REQUIRE(graph_force_layout_should_pause(1, 0));
}

TEST_CASE("should_pause emulating a low->high->low sequence", "[viz][pause]") {
    // Simula la logica del demo: el caller resetea low_frames cuando energy
    // sube. should_pause solo depende del valor actual.
    int low = 0;
    const int target = 5;

    // Acumulamos hasta 4: aun no.
    for (int i = 0; i < 4; ++i) {
        low++;
        REQUIRE_FALSE(graph_force_layout_should_pause(low, target));
    }

    // El caller detecta energia alta -> reset.
    low = 0;
    REQUIRE_FALSE(graph_force_layout_should_pause(low, target));

    // Acumulamos los 5 que pide el target.
    for (int i = 0; i < 5; ++i) low++;
    REQUIRE(graph_force_layout_should_pause(low, target));
}
