/**
 * Simple refrigeration cycle example for Entropyk C FFI.
 * 
 * Demonstrates:
 * - System lifecycle (create/free)
 * - Component creation (compressor, condenser, valve, evaporator)
 * - System topology (add components, add edges, finalize)
 * - Solving (fallback solver)
 * - Result retrieval
 */

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

int main() {
    printf("Entropyk C FFI Example - Simple Refrigeration Cycle\n");
    printf("===================================================\n\n");
    
    /* 1. Create the system */
    EntropykSystem* sys = entropyk_system_create();
    if (!sys) {
        printf("ERROR: Failed to create system\n");
        return 1;
    }
    printf("Created system\n");
    
    /* 2. Create components */
    double compressor_coeffs[10] = {
        0.85,   /* m1: mass flow coefficient */
        2.5,    /* m2: mass flow exponent for suction pressure */
        500.0,  /* m3: mass flow coefficient for superheat */
        1500.0, /* m4: power coefficient */
        -2.5,   /* m5: power exponent */
        1.8,    /* m6: power exponent */
        600.0,  /* m7: additional power coefficient */
        1600.0, /* m8: additional power coefficient */
        -3.0,   /* m9: power exponent */
        2.0     /* m10: power exponent */
    };
    
    EntropykComponent* comp = entropyk_compressor_create(compressor_coeffs, 10);
    EntropykComponent* cond = entropyk_condenser_create(5000.0);  /* 5 kW/K */
    EntropykComponent* valve = entropyk_expansion_valve_create();
    EntropykComponent* evap = entropyk_evaporator_create(3000.0);  /* 3 kW/K */
    
    if (!comp || !cond || !valve || !evap) {
        printf("ERROR: Failed to create components\n");
        entropyk_system_free(sys);
        return 1;
    }
    printf("Created 4 components: compressor, condenser, valve, evaporator\n");
    
    /* 3. Add components to system (transfers ownership, returns node index) */
    unsigned int comp_idx = entropyk_system_add_component(sys, comp);
    unsigned int cond_idx = entropyk_system_add_component(sys, cond);
    unsigned int valve_idx = entropyk_system_add_component(sys, valve);
    unsigned int evap_idx = entropyk_system_add_component(sys, evap);
    
    if (comp_idx == UINT32_MAX || cond_idx == UINT32_MAX ||
        valve_idx == UINT32_MAX || evap_idx == UINT32_MAX) {
        printf("ERROR: Failed to add component to system\n");
        entropyk_system_free(sys);
        return 1;
    }
    
    printf("Added components: comp=%u, cond=%u, valve=%u, evap=%u\n",
           comp_idx, cond_idx, valve_idx, evap_idx);
    
    /* 4. Connect components (simple cycle: comp -> cond -> valve -> evap -> comp) */
    EntropykErrorCode err;
    
    err = entropyk_system_add_edge(sys, comp_idx, cond_idx);
    if (err != ENTROPYK_OK) {
        printf("ERROR: Failed to add edge comp->cond: %s\n", entropyk_error_string(err));
        entropyk_system_free(sys);
        return 1;
    }
    
    err = entropyk_system_add_edge(sys, cond_idx, valve_idx);
    if (err != ENTROPYK_OK) {
        printf("ERROR: Failed to add edge cond->valve: %s\n", entropyk_error_string(err));
        entropyk_system_free(sys);
        return 1;
    }
    
    err = entropyk_system_add_edge(sys, valve_idx, evap_idx);
    if (err != ENTROPYK_OK) {
        printf("ERROR: Failed to add edge valve->evap: %s\n", entropyk_error_string(err));
        entropyk_system_free(sys);
        return 1;
    }
    
    err = entropyk_system_add_edge(sys, evap_idx, comp_idx);
    if (err != ENTROPYK_OK) {
        printf("ERROR: Failed to add edge evap->comp: %s\n", entropyk_error_string(err));
        entropyk_system_free(sys);
        return 1;
    }
    
    printf("Connected components in cycle\n");
    printf("System: %u nodes, %u edges\n",
           entropyk_system_node_count(sys),
           entropyk_system_edge_count(sys));
    
    /* 5. Finalize the system */
    err = entropyk_system_finalize(sys);
    if (err != ENTROPYK_OK) {
        printf("ERROR: Failed to finalize system: %s\n", entropyk_error_string(err));
        entropyk_system_free(sys);
        return 1;
    }
    printf("System finalized (state vector length: %u)\n",
           entropyk_system_state_vector_len(sys));
    
    /* 6. Configure and run solver */
    EntropykFallbackConfig config = {
        .newton = {
            .max_iterations = 100,
            .tolerance = 1e-6,
            .line_search = false,
            .timeout_ms = 0
        },
        .picard = {
            .max_iterations = 500,
            .tolerance = 1e-4,
            .relaxation = 0.5
        }
    };
    
    EntropykSolverResult* result = NULL;
    err = entropyk_solve_fallback(sys, &config, &result);
    
    /* 7. Check results */
    if (err == ENTROPYK_OK && result != NULL) {
        EntropykConvergenceStatus status = entropyk_result_get_status(result);
        unsigned int iterations = entropyk_result_get_iterations(result);
        double residual = entropyk_result_get_residual(result);
        
        printf("\n=== Solver Results ===\n");
        printf("Status: %s\n", 
               status == CONVERGED ? "CONVERGED" :
               status == CONVERGED_TIMED_OUT ? "TIMED_OUT" :
               status == CONVERGED_CONTROL_SATURATION ? "CONTROL_SATURATION" : "UNKNOWN");
        printf("Iterations: %u\n", iterations);
        printf("Final residual: %.2e\n", residual);
        
        /* Get state vector */
        unsigned int len = 0;
        entropyk_result_get_state_vector(result, NULL, &len);
        if (len > 0) {
            double* state = (double*)malloc(len * sizeof(double));
            if (state) {
                entropyk_result_get_state_vector(result, state, &len);
                printf("State vector[%u]: [", len);
                for (unsigned int i = 0; i < (len < 6 ? len : 6); i++) {
                    printf("%.2f", state[i]);
                    if (i < len - 1) printf(", ");
                }
                if (len > 6) printf(", ...");
                printf("]\n");
                free(state);
            }
        }
        
        entropyk_result_free(result);
    } else {
        printf("\n=== Solver Failed ===\n");
        printf("Error: %s\n", entropyk_error_string(err));
    }
    
    /* 8. Cleanup */
    entropyk_system_free(sys);
    printf("\nCleanup complete.\n");
    
    return (err == ENTROPYK_OK) ? 0 : 1;
}
