/**
 * @file test_cmd_dag.c
 * @brief Command Buffer DAG Unit Tests
 */

#include "mvgal/mvgal.h"
#include "mvgal/mvgal_cmd_dag.h"
#include "mvgal/mvgal_log.h"

#include <stdio.h>
#include <stdlib.h>

static int test_passed = 0;
static int test_failed = 0;

#define TEST_ASSERT(condition, message) \
    do { if (condition) { test_passed++; MVGAL_LOG_INFO("  ✓ %s", message); } \
         else { test_failed++; MVGAL_LOG_ERROR("  ✗ %s", message); } \
    } while (0)

static void test_dag_creation(void)
{
    MVGAL_LOG_INFO("--- DAG Creation ---");

    mvgal_cmd_dag_t* dag = mvgal_dag_create();
    TEST_ASSERT(dag != NULL, "DAG creation succeeds");
    TEST_ASSERT(dag->node_count == 0, "New DAG has zero nodes");

    mvgal_dag_destroy(dag);
    TEST_ASSERT(true, "DAG destruction succeeds");
}

static void test_node_addition(void)
{
    MVGAL_LOG_INFO("--- Node Addition ---");

    mvgal_cmd_dag_t* dag = mvgal_dag_create();
    
    mvgal_cmd_node_t* node = mvgal_dag_add_node(dag, MVGAL_CMD_DRAW);
    TEST_ASSERT(node != NULL, "Draw node added");
    TEST_ASSERT(dag->node_count == 1, "Node count is 1");

    mvgal_cmd_node_t* node2 = mvgal_dag_add_node(dag, MVGAL_CMD_DISPATCH);
    TEST_ASSERT(node2 != NULL, "Dispatch node added");
    TEST_ASSERT(dag->node_count == 2, "Node count is 2");

    mvgal_dag_destroy(dag);
}

static void test_dependency_handling(void)
{
    MVGAL_LOG_INFO("--- Dependency Handling ---");

    mvgal_cmd_dag_t* dag = mvgal_dag_create();
    
    mvgal_cmd_node_t* nodeA = mvgal_dag_add_node(dag, MVGAL_CMD_DISPATCH);
    mvgal_cmd_node_t* nodeB = mvgal_dag_add_node(dag, MVGAL_CMD_DRAW);
    
    mvgal_dag_add_dependency(nodeA, nodeB);
    TEST_ASSERT(nodeB->dep_count == 1, "Dependency added to B");
    
    /* Test duplicate prevention */
    mvgal_dag_add_dependency(nodeA, nodeB);
    TEST_ASSERT(nodeB->dep_count == 1, "Duplicate dependency ignored");

    mvgal_dag_destroy(dag);
}

static void test_cmd_recording(void)
{
    MVGAL_LOG_INFO("--- Command Recording ---");

    mvgal_cmd_dag_t* dag = mvgal_dag_create();
    
    mvgal_record_cmd_draw(dag, 1000, 1);
    TEST_ASSERT(dag->head != NULL, "Draw recorded");
    TEST_ASSERT(dag->head->type == MVGAL_CMD_DRAW, "Node is DRAW type");
    TEST_ASSERT(dag->head->args.draw.vertex_count == 1000, "Vertex count stored");

    mvgal_record_cmd_dispatch(dag, 64, 1, 1);
    TEST_ASSERT(dag->node_count == 2, "Dispatch recorded");

    mvgal_dag_destroy(dag);
}

static void test_null_safety(void)
{
    MVGAL_LOG_INFO("--- Null Safety ---");

    mvgal_dag_destroy(NULL);
    mvgal_dag_add_node(NULL, MVGAL_CMD_DRAW);
    mvgal_dag_add_dependency(NULL, NULL);
    
    TEST_ASSERT(true, "Null-safe operations handled");
}

int main(void)
{
    printf("\n============================================================\n");
    printf("  MVGAL Command Buffer DAG Unit Tests\n");
    printf("============================================================\n\n");

    test_dag_creation();
    test_node_addition();
    test_dependency_handling();
    test_cmd_recording();
    test_null_safety();

    printf("\n============================================================\n");
    printf("  Test Summary\n");
    printf("============================================================\n");
    printf("  Passed: %d\n", test_passed);
    printf("  Failed: %d\n", test_failed);
    printf("  Total:  %d\n", test_passed + test_failed);
    printf("============================================================\n\n");

    return (test_failed > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
}