// Unit tests for graph_renderer's RGBA8 packing helpers (cpp/functions/viz/
// graph_renderer.h). Roundtrip + alpha modulation + bit-layout match con
// unpackUnorm4x8 de GLSL (byte 0 = R, byte 3 = A) — el shader interpreta el
// uint32 sin swizzle, asi que el packing debe colocar R en el byte LSB.

#define CATCH_CONFIG_MAIN
#include "catch_amalgamated.hpp"

#include "viz/graph_renderer.h"

#include <cstdint>

TEST_CASE("pack_rgba8 places R in the LSB byte", "[viz][rgba8]") {
    uint32_t c = pack_rgba8(0x12, 0x34, 0x56, 0x78);
    REQUIRE(((c      ) & 0xFFu) == 0x12u); // R
    REQUIRE(((c >>  8) & 0xFFu) == 0x34u); // G
    REQUIRE(((c >> 16) & 0xFFu) == 0x56u); // B
    REQUIRE(((c >> 24) & 0xFFu) == 0x78u); // A
}

TEST_CASE("pack/unpack roundtrip is exact for arbitrary bytes", "[viz][rgba8]") {
    const uint8_t samples[] = { 0x00, 0x01, 0x7F, 0x80, 0xAB, 0xCD, 0xFE, 0xFF };
    for (uint8_t r : samples) for (uint8_t g : samples)
    for (uint8_t b : samples) for (uint8_t a : samples) {
        uint32_t c = pack_rgba8(r, g, b, a);
        uint8_t r2, g2, b2, a2;
        unpack_rgba8(c, r2, g2, b2, a2);
        REQUIRE(r == r2);
        REQUIRE(g == g2);
        REQUIRE(b == b2);
        REQUIRE(a == a2);
    }
}

TEST_CASE("modulate_alpha_rgba8 preserves RGB and scales alpha", "[viz][rgba8]") {
    uint32_t opaque = pack_rgba8(0x10, 0x20, 0x30, 0xFF);

    // Full pass-through: scale=1.0 -> alpha=255
    REQUIRE(modulate_alpha_rgba8(opaque, 1.0f) == opaque);

    // Half: alpha goes to 128 (255 * 0.5 + 0.5 = 128)
    uint32_t half = modulate_alpha_rgba8(opaque, 0.5f);
    uint8_t r, g, b, a;
    unpack_rgba8(half, r, g, b, a);
    REQUIRE(r == 0x10);
    REQUIRE(g == 0x20);
    REQUIRE(b == 0x30);
    REQUIRE(a == 128);

    // Zero: alpha goes to 0
    uint32_t zero = modulate_alpha_rgba8(opaque, 0.0f);
    unpack_rgba8(zero, r, g, b, a);
    REQUIRE(a == 0);
    // RGB intactos
    REQUIRE(r == 0x10);
    REQUIRE(g == 0x20);
    REQUIRE(b == 0x30);
}

TEST_CASE("modulate_alpha_rgba8 clamps overflow to 255", "[viz][rgba8]") {
    uint32_t c = pack_rgba8(1, 2, 3, 200);
    uint32_t out = modulate_alpha_rgba8(c, 5.0f); // 200*5 = 1000, clamp 255
    uint8_t r, g, b, a;
    unpack_rgba8(out, r, g, b, a);
    REQUIRE(a == 255);
    REQUIRE(r == 1);
    REQUIRE(g == 2);
    REQUIRE(b == 3);
}
