#include "libcurl.h"


struct MemoryStruct {
    char *memory;
    size_t size;
};

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    // 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if (ptr == NULL) {
        /* 内存不足！ */
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }

    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}

// 获取公网IP
char *curl_get_area(char *ip)
{
    char url[256] = { 0 };
    snprintf(url, sizeof(url), "https://qifu.baidu.com/ip/geo/v1/district?ip=%s", ip);
    
    
    CURL *curl_handle;
    CURLcode res;

    struct curl_slist *headers = NULL;
    struct MemoryStruct chunk;

    chunk.memory = malloc(1);   /* 将根据上述再分配的需要增长 */
    chunk.size = 0;             /* 此时没有数据 */

    curl_global_init(CURL_GLOBAL_ALL);

    /* 初始化curl会话 */
    curl_handle = curl_easy_init();

    char *p = NULL;
    char *buff;

    p = strstr(url, "-H");
    if (p) {

        buff = (char *)alloca(p - url + 1);
        if (buff == NULL)
            perror("out of memory.");

        memset(buff, 0, p - url + 1);
        memcpy(buff, url, (int)(p - url - 1));

        // 赋值header值
        headers = curl_slist_append(headers, p + 3);

        // 设置header
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl_handle, CURLOPT_URL, buff);

    } else {
        /* 指定要获取的URL */
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);

    }

    /* 将所有数据发送到此函数  */
    //对于同一次阻塞的curl_easy_perform而言，在写完获取的数据之前，会多次调用 WriteMemoryCallback
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

    /* 将"chunk"结构传递给回调函数 */
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    //对于同一次阻塞的curl_easy_perform而言，在写完获取的数据之前，会多次调用 WriteMemoryCallback
    res = curl_easy_perform(curl_handle);

    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    } else {
        //printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
        //printf("%s", chunk.memory);
        ;
    }

    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();

    return chunk.memory;
}

// 函数用于从 cJSON 对象提取字段内容
void parse_string_field(cJSON *parent, const char *field_name, char *output, size_t max_len) {
    cJSON *item = cJSON_GetObjectItemCaseSensitive(parent, field_name);
    if (cJSON_IsString(item) && item->valuestring) {
        strncpy(output, item->valuestring, max_len - 1);
        output[max_len - 1] = '\0'; // 确保字符串以 '\0' 结尾
    } else {
        output[0] = '\0'; // 如果字段不存在或不是字符串，设置为空字符串
    }
}

// 函数用于从 JSON 字符串解析为结构体
int parse_json_to_struct(const char *json_string, Response *response)
{
    if (!response) return -1;

    // 初始化结构体
    memset(response, 0, sizeof(Response));

    // 解析 JSON 字符串
    cJSON *root = cJSON_Parse(json_string);
    if (!root) {
        fprintf(stderr, "Error parsing JSON: %s\n", cJSON_GetErrorPtr());
        return -1;
    }

    // 解析字段
    parse_string_field(root, "code", response->code, sizeof(response->code));
    parse_string_field(root, "ip", response->ip, sizeof(response->ip));

    // 如果 code 不是 "Success"，直接返回
    if (strcmp(response->code, "Success") != 0) {
        fprintf(stderr, "Invalid code: %s\n", response->code);
        cJSON_Delete(root);
        return -1;
    }

    // 解析 data 对象
    cJSON *data_item = cJSON_GetObjectItemCaseSensitive(root, "data");
    if (cJSON_IsObject(data_item)) {
        parse_string_field(data_item, "continent", response->data.continent, sizeof(response->data.continent));
        parse_string_field(data_item, "country", response->data.country, sizeof(response->data.country));
        parse_string_field(data_item, "zipcode", response->data.zipcode, sizeof(response->data.zipcode));
        parse_string_field(data_item, "owner", response->data.owner, sizeof(response->data.owner));
        parse_string_field(data_item, "isp", response->data.isp, sizeof(response->data.isp));
        parse_string_field(data_item, "adcode", response->data.adcode, sizeof(response->data.adcode));
        parse_string_field(data_item, "prov", response->data.prov, sizeof(response->data.prov));
        parse_string_field(data_item, "city", response->data.city, sizeof(response->data.city));
        parse_string_field(data_item, "district", response->data.district, sizeof(response->data.district));
        parse_string_field(data_item, "region", response->data.region, sizeof(response->data.region));
    }

    snprintf(response->continent_country, 256, "%s%s", response->data.continent, response->data.country);
    
    // 清理 JSON 对象
    cJSON_Delete(root);
    return 0;
}


/*
int main(int argc, char *argv[])
{
    char *p = curl_get_area("1.1.1.1");
    puts(p);
    
    
    // 定义 Response 结构体
    Response response;

    // 解析 JSON 到结构体
    if (parse_json_to_struct(p, &response) == 0) {
        // 输出解析结果
        printf("Code: %s\n", response.code);
        printf("IP: %s\n", response.ip);
        printf("Continent: %s\n", response.data.continent);
        printf("Country: %s\n", response.data.country);
        printf("ISP: %s\n", response.data.isp);
        printf("Region: %s\n", response.data.region);
    } else {
        fprintf(stderr, "Failed to parse JSON.\n");
    }

    
    free(p);
}
*/