// file-level functions in napi_init.cpp
#include "napi/native_api.h"
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <pthread.h>

extern "C" int getStaticLibSum(int a, int b);
extern "C" const unsigned char* getStaticLibImage();
extern "C" int getStaticLibImageSize();

extern "C" int sample_add(int a, int b);
extern "C" const unsigned char* get_sample_image(void);
extern "C" int get_sample_image_size(void);

static napi_value TriggerHeapBufferOverflow(napi_env env, napi_callback_info /*info*/) {
    char *buffer;
    buffer = (char *)malloc(10);
    *(buffer + 11) = 'n'; // Overflow
    *(buffer + 12) = 'n'; // Overflow
    char ret = buffer[1]; // Read valid memory (though uninitialized)
    free(buffer);
    
    napi_value result;
    napi_create_int32(env, (int32_t)ret, &result);
    return result;
}

static int g_shared_var = 0;
static void* ThreadFunc(void* arg) {
    for (int i = 0; i < 100000; ++i) {
        g_shared_var++;
    }
    return nullptr;
}

static napi_value TriggerTsan(napi_env env, napi_callback_info /*info*/) {
    g_shared_var = 0;
    pthread_t t1, t2;
    pthread_create(&t1, nullptr, ThreadFunc, nullptr);
    pthread_create(&t2, nullptr, ThreadFunc, nullptr);
    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    napi_value result;
    napi_create_int32(env, (int32_t)g_shared_var, &result);
    return result;
}

static napi_value TriggerHwasanUseAfterFree(napi_env env, napi_callback_info /*info*/) {
    char* p = (char*)malloc(16);
    free(p);
    p[0] = 'x';
    int32_t ret = (int32_t)p[0];
    napi_value result;
    napi_create_int32(env, ret, &result);
    return result;
}

static napi_value NAPI_Global_getSampleImage(napi_env env, napi_callback_info info) {
    const unsigned char* data = get_sample_image();
    int size = get_sample_image_size();
    
    void* bufferData;
    napi_value arrayBuffer;
    napi_create_arraybuffer(env, size, &bufferData, &arrayBuffer);
    if (size > 0 && data != nullptr && bufferData != nullptr) {
        memcpy(bufferData, data, size);
    }
    
    return arrayBuffer;
}


static napi_value NAPI_Global_getKotlinSampleImage(napi_env env, napi_callback_info info) {
    // 调用 Kotlin 导出的函数
    const unsigned char* data = getStaticLibImage();
    int size = getStaticLibImageSize();
    
    void* bufferData;
    napi_value arrayBuffer;
    napi_create_arraybuffer(env, size, &bufferData, &arrayBuffer);
    if (size > 0 && data != nullptr && bufferData != nullptr) {
        memcpy(bufferData, data, size);
    }
    
    return arrayBuffer;
}


// Extern declarations for linked libkn.so functions
extern "C" {
    const char* getKotlinGreeting();
    const char* getKotlinUiText();
    const char* getKotlinAnalyticsInfo();
    int getStaticLibSum(int a, int b);
    int triggerKotlinHeapOverflow();
    int triggerKotlinHwasanError();
    void triggerCpuFreeze();
}


// 新增 NAPI 包装

static napi_value NAPI_Global_getStaticLibSum(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    double a = 0, b = 0;
    napi_get_value_double(env, args[0], &a);
    napi_get_value_double(env, args[1], &b);
    int r = getStaticLibSum(static_cast<int>(a), static_cast<int>(b));
    napi_value out;
    napi_create_int32(env, r, &out);
    return out;
}

static napi_value NAPI_Global_getKotlinAnalyticsInfo(napi_env env, napi_callback_info /*info*/) {
    const char* s = getKotlinAnalyticsInfo();
    napi_value out;
    napi_create_string_utf8(env, s, NAPI_AUTO_LENGTH, &out);
    return out;
}

static napi_value NAPI_Global_getKotlinGreeting(napi_env env, napi_callback_info /*info*/) {
    const char* s = getKotlinGreeting();
    napi_value out;
    napi_create_string_utf8(env, s, NAPI_AUTO_LENGTH, &out);
    return out;
}

static napi_value NAPI_Global_getKotlinUiText(napi_env env, napi_callback_info /*info*/) {
    const char* s = getKotlinUiText();
    napi_value out;
    napi_create_string_utf8(env, s, NAPI_AUTO_LENGTH, &out);
    return out;
}

static napi_value NAPI_Global_triggerKotlinHeapOverflow(napi_env env, napi_callback_info /*info*/) {
    int result = triggerKotlinHeapOverflow();
    napi_value out;
    napi_create_int32(env, result, &out);
    return out;
}

static napi_value NAPI_Global_triggerCpuFreeze(napi_env env, napi_callback_info /*info*/) {
    triggerCpuFreeze();
    return nullptr;
}


static napi_value NAPI_Global_getSampleAdd(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    double a = 0;
    double b = 0;
    napi_get_value_double(env, args[0], &a);
    napi_get_value_double(env, args[1], &b);
    int r = sample_add(static_cast<int>(a), static_cast<int>(b));
    napi_value out;
    napi_create_int32(env, r, &out);
    return out;
}



EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"getKotlinGreeting", nullptr, NAPI_Global_getKotlinGreeting, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getKotlinUiText", nullptr, NAPI_Global_getKotlinUiText, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getKotlinAnalyticsInfo", nullptr, NAPI_Global_getKotlinAnalyticsInfo, nullptr, nullptr, nullptr, napi_default, nullptr},
        // 新增：静态库合入的 Kotlin 导出
        {"getStaticLibSum", nullptr, NAPI_Global_getStaticLibSum, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getSampleAdd", nullptr, NAPI_Global_getSampleAdd, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getSampleImage", nullptr, NAPI_Global_getSampleImage, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getKotlinSampleImage", nullptr, NAPI_Global_getKotlinSampleImage, nullptr, nullptr, nullptr, napi_default, nullptr},
        // ASAN Trigger
        {"triggerHeapBufferOverflow", nullptr, TriggerHeapBufferOverflow, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"triggerHwasanUaf", nullptr, TriggerHwasanUseAfterFree, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"triggerTsan", nullptr, TriggerTsan, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"triggerKotlinHeapOverflow", nullptr, NAPI_Global_triggerKotlinHeapOverflow, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"triggerCpuFreeze", nullptr, NAPI_Global_triggerCpuFreeze, nullptr, nullptr, nullptr, napi_default, nullptr},
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}