#include <cjson/cJSON.h>
#include <syslog.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "common_utils.h"


/**
 * Safely get JSON float value
 * @param root      JSON root node (must be cJSON object)
 * @param key       Key name to retrieve  
 * @param value_p   Pointer to store float result
 * @param file      Caller filename (pass __FILE__)
 * @param line      Caller line number (pass __LINE__)
 * @return bool     Returns true on success, false on failure
 */
bool get_json_float_safe(cJSON *root, const char *key, float *value_p, const char *file, int line)
{
    // Basic parameter validation
    if (unlikely(!root || !key || !value_p)) {
        syslog(LOG_ERR, "[%s:%d] Parameter error: root=%p, key=%s, value_p=%p", 
               file, line, (void*)root, key ? key : "NULL", (void*)value_p);
        return false;
    }

    // Type checking
    if (!cJSON_IsObject(root)) {
        syslog(LOG_ERR, "[%s:%d] root is not JSON object", file, line);
        return false;
    }

    // Get field
    cJSON *item = cJSON_GetObjectItem(root, key);
    if (!item) {
        syslog(LOG_DEBUG, "[%s:%d] Key [%s] not found", file, line, key);
        return false;
    }

    // Type verification
    if (!cJSON_IsNumber(item)) {
        syslog(LOG_ERR, "[%s:%d] Key [%s] is not number type", file, line, key);
        return false;
    }

    *value_p = item->valuedouble;
    return true;
}


/**
 * Safely get JSON float value
 * @param root      JSON root node (must be cJSON object)
 * @param key       Key name to retrieve  
 * @param value_p   Pointer to store float result
 * @param file      Caller filename (pass __FILE__)
 * @param line      Caller line number (pass __LINE__)
 * @return bool     Returns true on success, false on failure
 */
bool get_json_double_safe(cJSON *root, const char *key, double *value_p, const char *file, int line)
{
    // Basic parameter validation
    if (unlikely(!root || !key || !value_p)) {
        syslog(LOG_ERR, "[%s:%d] Parameter error: root=%p, key=%s, value_p=%p", 
               file, line, (void*)root, key ? key : "NULL", (void*)value_p);
        return false;
    }

    // Type checking
    if (!cJSON_IsObject(root)) {
        syslog(LOG_ERR, "[%s:%d] root is not JSON object", file, line);
        return false;
    }

    // Get field
    cJSON *item = cJSON_GetObjectItem(root, key);
    if (!item) {
        syslog(LOG_DEBUG, "[%s:%d] Key [%s] not found", file, line, key);
        return false;
    }

    // Type verification
    if (!cJSON_IsNumber(item)) {
        syslog(LOG_ERR, "[%s:%d] Key [%s] is not number type", file, line, key);
        return false;
    }

    *value_p = item->valuedouble;
    return true;
}

/**
 * Safely get JSON integer value
 * @param root      JSON root node
 * @param key       Key name to retrieve
 * @param value_p   Pointer to store integer result  
 * @param file      Caller filename
 * @param line      Caller line number
 * @return bool     Returns true on success, false on failure
 */
bool get_json_int_safe(cJSON *root, const char *key, int *value_p, 
                            const char *file, int line)
{
    // Basic parameter validation
    if (unlikely(!root || !key || !value_p)) {
        syslog(LOG_ERR, "[%s:%d] Parameter error: root=%p, key=%s, value_p=%p",
               file, line, (void*)root, key ? key : "NULL", (void*)value_p); 
        return false;
    }

    // Type checking
    if (!cJSON_IsObject(root)) {
        syslog(LOG_ERR, "[%s:%d] root is not JSON object", file, line);
        return false;
    }

    // Get field
    cJSON *item = cJSON_GetObjectItem(root, key);
    if (!item) {
        syslog(LOG_DEBUG, "[%s:%d] Key [%s] not found", file, line, key);
        return false;
    }

    // Type verification
    if (!cJSON_IsNumber(item)) {
        syslog(LOG_ERR, "[%s:%d] Key [%s] is not number type", file, line, key);
        return false;
    }

    *value_p = item->valueint;
    return true;
}

/**
 * Safely get JSON string value
 * @param root      JSON root node
 * @param key       Key name to retrieve
 * @param str_buf   String buffer for storage
 * @param buf_size  Buffer size
 * @param file      Caller filename
 * @param line      Caller line number
 * @return bool     Returns true on success, false on failure
 */
bool get_json_string_safe(cJSON *root, const char *key, char *str_buf, size_t buf_size, 
                               const char *file, int line)
{
    // Basic parameter validation
    if (unlikely(!root || !key || !str_buf)) {
        syslog(LOG_ERR, "[%s:%d] Parameter error: root=%p, key=%s, str_buf=%p", 
               file, line, (void*)root, key ? key : "NULL", (void*)str_buf);
        return false;
    }

    // Type checking
    if (!cJSON_IsObject(root)) {
        syslog(LOG_ERR, "[%s:%d] root is not JSON object", file, line);
        return false;
    }

    // Get field
    cJSON *item = cJSON_GetObjectItem(root, key);
    if (!item) {
        syslog(LOG_DEBUG, "[%s:%d] Key [%s] not found", file, line, key);
        return false;
    }

    // Type verification
    if (!cJSON_IsString(item)) {
        syslog(LOG_ERR, "[%s:%d] Key [%s] is not string type", file, line, key);
        return false;
    }

    // Safe string copy
    strncpy(str_buf, item->valuestring, buf_size - 1);
    str_buf[buf_size - 1] = '\0';
    return true;
}





