/**
 * Test: Memory leak detection
 * 
 * This test should be run with valgrind or ASAN to detect memory leaks.
 * 
 * Usage:
 *   valgrind --leak-check=full --error-exitcode=1 ./test_memory
 * 
 * Or compile with ASAN:
 *   gcc -fsanitize=address -o test_memory test_memory.c -L../../../target/release -lentropyk_ffi
 *   ./test_memory
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "entropyk.h"

#define NUM_CYCLES 100

int main() {
    printf("Test: Memory leak detection\n");
    printf("  Run with: valgrind --leak-check=full ./test_memory\n\n");
    
    /* Test 1: System lifecycle */
    printf("  Test 1: System create/free cycles (%d iterations)... ", NUM_CYCLES);
    for (int i = 0; i < NUM_CYCLES; i++) {
        EntropykSystem* sys = entropyk_system_create();
        assert(sys != NULL);
        entropyk_system_free(sys);
    }
    printf("PASS\n");
    
    /* Test 2: Component lifecycle (not added to system) */
    printf("  Test 2: Component create/free cycles... ");
    for (int i = 0; i < NUM_CYCLES; i++) {
        double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
        EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
        EntropykComponent* cond = entropyk_condenser_create(5000.0);
        EntropykComponent* evap = entropyk_evaporator_create(3000.0);
        EntropykComponent* valve = entropyk_expansion_valve_create();
        
        assert(comp && cond && evap && valve);
        
        entropyk_compressor_free(comp);
        entropyk_component_free(cond);
        entropyk_component_free(evap);
        entropyk_component_free(valve);
    }
    printf("PASS\n");
    
    /* Test 3: Full system with components (ownership transfer) */
    printf("  Test 3: Full system lifecycle... ");
    for (int i = 0; i < NUM_CYCLES; i++) {
        EntropykSystem* sys = entropyk_system_create();
        assert(sys != NULL);
        
        double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
        EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
        EntropykComponent* cond = entropyk_condenser_create(5000.0);
        EntropykComponent* evap = entropyk_evaporator_create(3000.0);
        EntropykComponent* valve = entropyk_expansion_valve_create();
        
        unsigned int comp_idx = entropyk_system_add_component(sys, comp);
        unsigned int cond_idx = entropyk_system_add_component(sys, cond);
        unsigned int evap_idx = entropyk_system_add_component(sys, evap);
        unsigned int valve_idx = entropyk_system_add_component(sys, valve);
        
        (void)comp_idx; (void)cond_idx; (void)evap_idx; (void)valve_idx;
        
        entropyk_system_free(sys);
        /* Note: Components are freed when system is freed (ownership transfer) */
    }
    printf("PASS\n");
    
    /* Test 4: Solver result lifecycle */
    printf("  Test 4: Solver result lifecycle... ");
    for (int i = 0; i < NUM_CYCLES; i++) {
        EntropykSystem* sys = entropyk_system_create();
        
        double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
        EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
        EntropykComponent* cond = entropyk_condenser_create(5000.0);
        EntropykComponent* evap = entropyk_evaporator_create(3000.0);
        EntropykComponent* valve = entropyk_expansion_valve_create();
        
        entropyk_system_add_component(sys, comp);
        entropyk_system_add_component(sys, cond);
        entropyk_system_add_component(sys, evap);
        entropyk_system_add_component(sys, valve);
        
        entropyk_system_finalize(sys);
        
        EntropykFallbackConfig config = {
            .newton = {10, 1e-4, false, 100},
            .picard = {20, 1e-3, 0.5}
        };
        
        EntropykSolverResult* result = NULL;
        entropyk_solve_fallback(sys, &config, &result);
        
        if (result != NULL) {
            entropyk_result_free(result);
        }
        
        entropyk_system_free(sys);
    }
    printf("PASS\n");
    
    /* Test 5: Null pointer handling (should not crash or leak) */
    printf("  Test 5: Null pointer handling... ");
    entropyk_system_free(NULL);
    entropyk_compressor_free(NULL);
    entropyk_component_free(NULL);
    entropyk_result_free(NULL);
    printf("PASS\n");
    
    /* Test 6: State vector retrieval */
    printf("  Test 6: State vector allocation... ");
    EntropykSystem* sys = entropyk_system_create();
    double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
    EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
    EntropykComponent* cond = entropyk_condenser_create(5000.0);
    EntropykComponent* evap = entropyk_evaporator_create(3000.0);
    EntropykComponent* valve = entropyk_expansion_valve_create();
    
    entropyk_system_add_component(sys, comp);
    entropyk_system_add_component(sys, cond);
    entropyk_system_add_component(sys, evap);
    entropyk_system_add_component(sys, valve);
    entropyk_system_finalize(sys);
    
    EntropykFallbackConfig config = {
        .newton = {10, 1e-4, false, 100},
        .picard = {20, 1e-3, 0.5}
    };
    
    EntropykSolverResult* result = NULL;
    if (entropyk_solve_fallback(sys, &config, &result) == ENTROPYK_OK && result != NULL) {
        unsigned int len = 0;
        entropyk_result_get_state_vector(result, NULL, &len);
        if (len > 0) {
            double* state = (double*)malloc(len * sizeof(double));
            entropyk_result_get_state_vector(result, state, &len);
            free(state);
        }
        entropyk_result_free(result);
    }
    entropyk_system_free(sys);
    printf("PASS\n");
    
    printf("\nAll memory tests PASSED\n");
    printf("If running under valgrind, check for 'ERROR SUMMARY: 0 errors'\n");
    return 0;
}
