#include "cJSON.h"

#include <tc/tc.h>
#include "epm_handler_common.h"
#include <ict/ict_userservice.h>
#include <tccore/custom.h>
#include <epm/epm_toolkit_tc_utils.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <tccore/item.h>
#include <bom/bom.h>
#include "ps/ps.h";
#include "ps/vrule.h"
#include "sstream"
#include <tccore/grm.h>
#include "epm/epm.h"
#include "sa/sa.h"
#include "libxl.h"
#include <map>
#include "epm/signoff.h"
#include <ctime>
#include <vector>
#include <locale>
#include <codecvt>
#include "ae/dataset.h"
#include <iostream>
#include <stdlib.h>
#include <tccore/aom.h>
#include <tc/emh.h>
#include <ict/ict_userservice.h>
#include <tc/tc.h>
#include <tccore/tctype.h>
#include <sa/tcfile.h>
#include <ss/ss_errors.h>
#include <ae/datasettype.h>
#include "chint_Handler.h"
#include <regex>
#include <ics/ics.h>
#include "ado.h"
#include "ocilib.h"
#include <property/nr.h>
#include "CRUL_server_call_httpserver.h"
#include "common_itk_util.h"
#include <chrono>
#include <cctype>  // for std::isspace
#include <string>
#include <algorithm>
#define EPM_HANDLER_COMMON
#define MAX_PATH_LENGTH 200
#define MAX_PRINTLINE_LENGTH 400000

std::string removeWhitespace(const std::string& str) {
	std::string result;
	result.reserve(str.size()); // 预留空间以提高性能

								// 使用 std::copy_if 和 std::isspace 来过滤掉空白字符
	std::copy_if(str.begin(), str.end(), std::back_inserter(result),
		[](unsigned char ch) { return !std::isspace(ch); });

	return result;
}

// 转义json字符串
void escapeJson2(std::string& str) {
	int len = str.length();
	int newLen = len;
	for (int i = 0; i < len; i++) {
		if (str[i] == '"' || str[i] == '\\') {
			newLen++;
		}
	}
	std::string escapedStr;
	escapedStr.reserve(newLen);
	for (int i = 0; i < len; i++) {
		if (str[i] == '"' || str[i] == '\\') {
			escapedStr.push_back('\\');
		}
		escapedStr.push_back(str[i]);
	}
	str = escapedStr;
}

char* concat(char** s, int size) {
	int length = 0;
	for (int i = 0; i < size; i++) {
		length += strlen(s[i]);
	}
	char* result = new char[length + 1];
	int index = 0;
	for (int i = 0; i < size; i++) {
		int len = strlen(s[i]);
		memcpy(result + index, s[i], len);
		index += len;
	}
	result[length] = '\0';
	return result;
}

char* utogbm(const char* src_str)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0);
	wchar_t* wszGBK = (wchar_t*)MEM_alloc((len + 1) * sizeof(wchar_t));
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len);
	len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
	char* szGBK = (char*)MEM_alloc((len + 1) * sizeof(char));

	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
	return szGBK;
}

char* gtoubm(const char* src_str)
{
	int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0);
	wchar_t* wstr = (wchar_t*)MEM_alloc((len + 1) * sizeof(wchar_t));
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = (char*)MEM_alloc((len + 1) * sizeof(char));

	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	return str;
}


// 写入回调函数实现
size_t WriteCallbackbm(void* contents, size_t size, size_t nmemb, void* userp) {
	size_t totalSize = size * nmemb;
	char* buffer = (char*)userp;

	// 追加内容到缓冲区
	strncat(buffer, (char*)contents, totalSize);

	return totalSize; // 返回实际接收的字节数
}

void feishuSplitbm(string strArg, string spliter, vector<string>& ans)
{
	ans.clear();
	size_t index0 = 0;
	string one_arg;
	if (strArg.find_first_not_of(' ') == string::npos)
		strArg = "";
	while (strArg.size() > 0)
	{
		index0 = strArg.find_first_of(spliter);
		if (index0 != string::npos)
		{
			one_arg = strArg.substr(0, index0);
			strArg = strArg.substr(index0 + 1);
			ans.push_back(one_arg);
		}
		else
		{
			ans.push_back(strArg);
			break;
		}
	}
}


void WriteLogbm(logical debug, const char* format, ...)
{
	va_list arg;
	char tmp[MAX_PRINTLINE_LENGTH];
	char date_string[MAX_PATH_LENGTH];
	time_t now;
	struct tm* p;

	//get the message
	memset(tmp, 0, sizeof(tmp));
	va_start(arg, format);
	vsprintf(tmp, format, arg);
	va_end(arg);
	//----------print to command window for trace--------//
	//printf("%s\n", tmp);
	printf("%s\n", tmp);
	//print message to log file
	TC_write_syslog("%s\n", tmp);
}
int chint_changenoticebm(EPM_action_message_t msg) {

	tag_t task_tag = NULL_TAG,
		root_task_tag = NULLTAG,
		*attachments;;
	task_tag = msg.task;
	int att_cnt = 0, ifail = 0;
	int c_sql_value_count = 0;
	char** c_sql_values = NULL;
	ITKCALL(PREF_ask_char_values("CHINT_ChangeNoticeBM", &c_sql_value_count, &c_sql_values));

	WriteLogbm(true, "------------------------------------------------------------------------------------");
	WriteLogbm(true, "=========================");
	WriteLogbm(true, "chint_changenoticebm start");
	WriteLogbm(true, "=========================");

	EPM_ask_root_task(task_tag, &root_task_tag);
	EPM_ask_attachments(root_task_tag, EPM_target_attachment, &att_cnt, &attachments);
	WriteLogbm(true, "流程目标下的对象数量：%d", att_cnt);

	//分割首选项
	string finalUsers = "";
	std::map<std::string, std::string> prefMap;//统计集合
	std::map<std::string, std::string> zt2_ChangeUnit1Map;//zt2_ChangeUnit1  map
	for (int j = 0; j < c_sql_value_count; j++) {

		/*触发handler后获取当前流程目标下 “ZT2_Change”对象的item属性更改单发放部门“zt2_ChangeUnit1”
		与首选项“CHINT_ChangeNoticeBM”中的已定义的值（“ | ”后面的值）进行匹配
		，（“ | ”前面的值与变更单所有者所在的组真实值匹配）并以飞书通知的形式通知给相关 的人员。
		通知信息：由“变更申请人”发起的 + ”更改单号” + 首选项第一行的内容＋（项目名称 - 项目wbs号 - 图号：xx; xx）*/
		if (j != 0) {
			vector<string> ans;
			feishuSplitbm(c_sql_values[j], "|", ans);
			prefMap[ans[0]] = ans[1];
		}

	}
	WriteLogbm(true, "首选项条数：%d", prefMap.size());
	for (int i = 0; i < att_cnt; i++)
	{
		tag_t tagt = NULLTAG;
		tagt = attachments[i];
		char* type, *zt2_ChangeUnit1;
		//获取版本下的数据集
		int dataset_num = 0;
		tag_t* dataset_tags = NULL;
		char* tempValue = NULL;
		char taskpuid[56] = "\0";
		ITK__convert_tag_to_uid(task_tag, &tempValue);
		tc_strcpy(taskpuid, tempValue);
		ITKCALL(AOM_ask_value_string(tagt, "object_type", &type));
		printf("object_type=%s\n", type);
		//获取当前登入人组
		//char* groupName = NULL;
		//tag_t t_group = NULLTAG;
		//ITKCALL(POM_ask_group(&groupName, &t_group));
		//printf("g=%s\n", groupName);
		//获取当前登入人的名称和id

		tag_t group;
		char* group_name;
		AOM_ask_value_tag(tagt, "owning_group", &group);
		AOM_ask_value_string(group, "name", &group_name);


		char* name;
		char* id;
		tag_t user;
		POM_get_user(&name, &user);
		POM_get_user_id(&id);
		printf("name================%s\n", name);
		printf("id================%s\n", id);
		printf("group_name================%s\n", group_name);
		string users = "";
		//判断组是否在首选项中存在
		for (auto it = prefMap.begin(); it != prefMap.end(); it++) {
			//当前组和首选项中组匹配
			if (strcmp(it->first.c_str(), group_name) == 0) {
				users = it->second;
				break;
			}
		}

		printf("users================%s\n", users.c_str());
		if (strcmp(users.c_str(), "") != 0) {
			//判断目标下是否存在  ZT2_Change

			if (strcmp("ZT2_Change", type) == 0) {
				//获取zt2_ChangeUnit1的值
				int num; char** getValues;
				ITKCALL(AOM_UIF_ask_values(tagt, "zt2_ChangeUnit1", &num, &getValues));
				zt2_ChangeUnit1 = concat(getValues, num);
				printf("zt2_ChangeUnit1===========%s\n", zt2_ChangeUnit1);
				//分割";"
				vector<string> zt2_ChangeUnit1Ans;
				feishuSplitbm(users, ";", zt2_ChangeUnit1Ans);
				for (int z = 0; z < zt2_ChangeUnit1Ans.size(); z++) {
					vector<string> tempSplit;
					feishuSplitbm(zt2_ChangeUnit1Ans[z], ":", tempSplit);
					zt2_ChangeUnit1Map[tempSplit[0]] = tempSplit[1];
				}
				printf("zt2_ChangeUnit1Map===========%d\n", zt2_ChangeUnit1Map.size());
				//遍历zt2_ChangeUnit1Map，把zt2_ChangeUnit1中与首选项匹配
				for (auto it = zt2_ChangeUnit1Map.begin(); it != zt2_ChangeUnit1Map.end(); it++) {
					//当前组和首选项中组匹配
					if (strstr(zt2_ChangeUnit1, it->first.c_str())) {
						finalUsers.append(it->second).append(",");
					}
				}
				printf("finalUsers===========%s\n", finalUsers.c_str());

				if (strcmp(finalUsers.c_str(), "") != 0) {


					//拼接json
					char* json = NULL;
					string contentStr;
					cJSON* top = cJSON_CreateObject();
					cJSON* emails = cJSON_CreateArray();
					cJSON* mobiles = cJSON_CreateArray();



					//拼接emails
					vector<string> usersVector;



					std::map<std::string, std::string> tempMap;//zt2_ChangeUnit1  map
															   //取唯一先放入map里
					feishuSplitbm(finalUsers, ",", usersVector);
					for (int h = 0; h < usersVector.size(); h++) {
						tempMap[usersVector[h].c_str()] = usersVector[h].c_str();
					}

					for (auto it = tempMap.begin(); it != tempMap.end(); it++) {
						//当前组和首选项中组匹配
						cJSON* new_string = cJSON_CreateString(it->first.c_str());
						cJSON_AddItemToArray(emails, new_string);
					}

					//找项目信息



					//拼接content  
					tag_t user;
					char* duser, *itemId;
					char* zt2_WBSNo, *zt2_ContractName;
					AOM_ask_value_string(tagt, "item_id", &itemId);
					AOM_ask_value_string(tagt, "zt2_WBSNo", &zt2_WBSNo);
					AOM_ask_value_string(tagt, "zt2_ContractName", &zt2_ContractName);

					string th = "";
					int wlNum; tag_t* wlTags;
					ITKCALL(AOM_ask_value_tags(tagt, "ZT2_ChangeAfter", &wlNum, &wlTags));
					printf("wlNum======%d\n", wlNum);
					for (int j = 0; j < wlNum; j++) {
						char* thType;
						AOM_ask_value_string(wlTags[j], "object_type", &thType);
						if (strcmp(thType, "ZT2_Design3DRevision") == 0) {
							char* thid;
							AOM_ask_value_string(wlTags[j], "item_id", &thid);
							th.append(thid).append(";");
						}

					}
					printf("th======%s\n", th);

					AOM_ask_value_tag(tagt, "owning_user", &user);
					AOM_ask_value_string(user, "user_name", &duser);
					//获取当前时间

					auto now = std::chrono::system_clock::now();
					std::time_t time = std::chrono::system_clock::to_time_t(now);
					std::tm* ptm = std::localtime(&time);
					char buf[128];
					strftime(buf, sizeof(buf), "%Y.%m.%d", ptm);
					printf("time===%s\n", buf);
					contentStr.append(duser).append(" 发起的").append(itemId).append(c_sql_values[0]).append("(").append(th).append("-").append(zt2_WBSNo).append("-").append(zt2_ContractName).append(") 发起人:").append(duser).append("发布时间:").append(buf);
					cJSON_AddStringToObject(top, "content", contentStr.c_str());

					//sms
					cJSON_AddStringToObject(top, "sms", "false");



					cJSON_AddItemToObject(top, "emails", emails);
					cJSON_AddItemToObject(top, "mobiles", mobiles);

					json = cJSON_Print(top);

					printf("json================%s\n", json);
					string result;
					result.append(json);
					escapeJson2(result);


					string result1 = removeWhitespace(result);
					printf("result1=============%s\n", result1.c_str());
					// lidy20240829新接口
					string cmd = "java -jar \"";
					cmd.append(getenv("TC_ROOT")).append("\\bin\\uploadMinio.jar\" FS \"").append(result1).append("\"");


					printf("cmd==>%s", cmd.c_str());
					FILE* pf = NULL;
					string strResult;
					char buf2[8000] = { 0 };
					if ((pf = _popen(cmd.c_str(), "r")) == NULL) {
						printf("接口返回1\n");
					}
					else {
						printf("接口返回2\n");
						while (fgets(buf2, sizeof buf2, pf)) {
							strResult += buf2;
						}
						_pclose(pf);
					}



					//调用接口
					/*CURL* curl;
					CURLcode res;
					char readBuffer[10000];
					memset(readBuffer, 0, 10000);
					curl = curl_easy_init();
					if (curl) {
					curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
					curl_easy_setopt(curl, CURLOPT_URL, "http://10.128.10.170/api/feishu/Message/sendMessages");
					curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
					curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
					struct curl_slist* headers = NULL;
					curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallbackbm);
					// 设置写入数据的目标缓冲区

					curl_easy_setopt(curl, CURLOPT_WRITEDATA, readBuffer);
					headers = curl_slist_append(headers, "Content-Type: application/json");
					curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
					//const char* data = "{\"emails\":[\"shaojq@chint.com\",\"zouy5@chint.com\"],\"mobiles\":[],\"sms\":false,\"content\":\"项目编号:P2303344售前资料已经获取完毕，请 登陆PLM系统查看。\"}";
					curl_easy_setopt(curl, CURLOPT_POSTFIELDS, gtoubm(json));
					res = curl_easy_perform(curl);
					}
					curl_easy_cleanup(curl);*/


					char* gbk_readBuffer = utogbm(strResult.c_str());
					printf("json================%s\n", gbk_readBuffer);
					cJSON* result_json = cJSON_Parse(gbk_readBuffer);
					cJSON* code = cJSON_GetObjectItem(result_json, "code");

					int code_int = code->valueint;

					if (code_int != 0) {
						printf("发送飞书失败\n");
					}

				}



			}

		}









	}


	DOFREE(attachments);
	WriteLogbm(true, "=========================");
	WriteLogbm(true, "chint_changenoticebm end");
	WriteLogbm(true, "=========================");
	return ifail;
}