#pragma warning (disable: 4996) 
#pragma warning (disable: 4819) 
#include <cstdio>
#include <io.h>
#include <epm/epm.h>
#include <ict/ict_userservice.h>
#include <tccore/item.h>
#include <ae/ae.h>
#include <tc/folder.h>
#include <tccore/aom.h>
#include <sa/sa.h>
#include <tccore/aom_prop.h>
#include <tccore/workspaceobject.h>
#include <tccore//grm.h>
#include <tccore/grmtype.h>
#include <bom/bom.h>
#include <fclasses/tc_date.h>
#include <ics/ics.h>
#include <ics/ics2.h>
#include "tc_util.h"
#include "tc_log.h"
#include <vector>
#include <epm/signoff.h>
#include <iostream>
#include "string_utils.h"
#include "tinyxml.h"
#include "ado.h"
#include <stdio.h>
#include <time.h>
using namespace std;
extern "C" int POM_AM__set_application_bypass(logical bypass);
string readXML(map<string, map<vector<string>, vector<string>>> &xmlMap, string xmlPath) {
	time_t currentTime;
	struct tm *timeInfo;
	char timeString[80];
	// 获取当前时间
	time(&currentTime);
	// 将时间转换为本地时间
	timeInfo = localtime(&currentTime);
	TiXmlDocument* pDoc = new TiXmlDocument();
	pDoc->LoadFile(xmlPath.c_str());
	//pDoc->Print();
	//获取根节点
	TiXmlElement* pRoot = pDoc->RootElement();
	string rootName = pRoot->Value();
	string t_Item_info = rootName;//
	//获取Item标签
	TiXmlElement* itemElement = pRoot->FirstChildElement("ITEM");//物料类型
	string itemLable = itemElement->Value();
	TiXmlElement *nextItemElement = itemElement;
	//循环遍历根节点下的兄弟节点
	char type[50] = "";
	char sessionId[50] = "";
	char transNowTime[50] = "";
	char transStatus[50] = "";
	char itemId[50] = "";
	char itemRev[50] = "";
	char itemName[50] = "";
	char itemRelease[50] = "";
	while (nextItemElement) {
		map<vector<string>, vector<string>> propertyMap;//字段名集合，值的集合
		vector<string> nameVec;
		vector<string> valueVec;
		const char* attribute_value = nextItemElement->Attribute("type");
		if (attribute_value == NULL) {
			strcpy(type, "通用");
		}
		else {
			strcpy(type, attribute_value);
		}
		WriteLog("type=%s\n", type);
		string materialType = type;
		TiXmlElement* pChild = nextItemElement->FirstChildElement();
		if (pChild != NULL) {
			string childLabnelName = pChild->Value();
			attribute_value = pChild->Attribute("val");
			strcpy(sessionId, attribute_value);  // 将 str 复制给 copy
			string tempValue = sessionId;
			nameVec.push_back(childLabnelName);
			valueVec.push_back(tempValue);
		}
		pChild = pChild->NextSiblingElement();
		while (true) {
			if (pChild != NULL) {
				string childLabnelName = pChild->Value();
				attribute_value = pChild->Attribute("val");
				strcpy(sessionId, attribute_value);  // 将 str 复制给 copy
				string tempValue = sessionId;
				nameVec.push_back(childLabnelName);
				if (strcmp("TRANSNO", childLabnelName.c_str()) == 0) {
					strftime(timeString, sizeof(timeString), sessionId, timeInfo);
					tempValue = timeString;
				}
				valueVec.push_back(tempValue);
			}
			;
			pChild = pChild->NextSiblingElement();
			if (pChild == NULL) {
				break;
			}
		}
		propertyMap[nameVec] = valueVec;
		xmlMap[materialType] = propertyMap;
		nextItemElement = nextItemElement->NextSiblingElement();
	}
	delete pDoc;//
	return t_Item_info;
}

/**
 * 去掉字符串首尾的单引号
 */
void removeQuotes(char* tempValue) {
	if (tempValue == nullptr) return;

	size_t len = strlen(tempValue);

	// 移除开头的单引号
	if (len > 0 && tempValue[0] == '\'') {
		memmove(tempValue, tempValue + 1, len);
		len--;
	}

	// 移除末尾的单引号
	if (len > 0 && tempValue[len - 1] == '\'') {
		tempValue[len - 1] = '\0';
	}
}

int JD_ItemInfoToMediDatabase(EPM_action_message_t msg) {
	bool showError = false;
	nowTime();
	time_t now;
	struct tm *p;
	//获取当前时间
	time(&now);
	//本地化时间，可以细分为年月日时分秒等
	p = localtime(&now);
	char TC_LOG_FILE[128] = "";
	createDir();//创建日志目录
	// 把日志名称赋予给某变量
	sprintf_s(TC_LOG_FILE, "%s\\tmplog\\JD_ItemInfoToMediDatabase_log_[%d-%d-%d-%d-%02d-%02d].txt", getenv("TEMP"), 1900 + p->tm_year, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min,p->tm_sec);
	ECHO("创建日志文件[%s]\n", TC_LOG_FILE);
	CreateLogFile(TC_LOG_FILE);
	//流程节点相关
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int arg_cnt = 0, ifail = 0;
	char arg1value[1024] = "";//物料类型
	char *argflag = NULL, *argvalue = NULL, *arg = NULL;
	//得到触发此函数的节点
	current_task = msg.task;
	WriteLog("=========================================================\n");
	WriteLog("JD_ItemInfoToMediDatabase 开始执行\n");
	WriteLog("=========================================================\n");
	//获取handler的参数的个数
	arg_cnt = TC_number_of_arguments(msg.arguments);
	WriteLog("参数个数为：%d\n", arg_cnt);
	if (arg_cnt > 0)
	{
		for (int i = 0; i < arg_cnt; i++)
		{
			//获取下一个参数（从0开始）
			arg = TC_next_argument(msg.arguments);
			//获取参数的名称和值
			ifail = ITK_ask_argument_named_value((const char*)arg, &argflag, &argvalue);
			if (stricmp(argflag, "PartItem") == 0)
			{
				if (argvalue != NULL)
				{
					strcpy(arg1value, argvalue);
				}
			}
		}
		MEM_free(argflag);
		MEM_free(argvalue);
	}
	//先获取首选项Jd_Erp_Info_Connect，解析其中的用户名，密码，配置文件等信息
	vector<string>		pref_vec1;
	getPrefStrings1("Jd_Erp_Info_Connect_Test", TC_preference_site, pref_vec1);
	string ip = pref_vec1[0];
	string databaseName = pref_vec1[1];
	string user = pref_vec1[2];
	string password = pref_vec1[3];
	string xmlUid = pref_vec1[4];
	WriteLog("ip:%s\n", ip.c_str());
	WriteLog("databaseName:%s\n", databaseName.c_str());
	WriteLog("user:%s\n", user.c_str());
	WriteLog("password:%s\n", password.c_str());
	WriteLog("xmlUid:%s\n", xmlUid.c_str());
	ado ado0;
	char userName[100];
	strcpy(userName, user.c_str());
	char pwd[100];
	strcpy(pwd, password.c_str());
	string info = "Provider=SQLOLEDB.1;Persist Security Info=False;Initial Catalog=";
	info.append(databaseName).append(";Data Source=").append(ip);
	WriteLog("连接信息：%s\n", info.c_str());
	bool log = ado0.open(userName, pwd, info.c_str());
	tag_t wlinfoXml = NULL;
	ITK__convert_uid_to_tag(xmlUid.c_str(), &wlinfoXml);
	//获取文件
	char *temp_dir = getenv("temp");//获得缓存路径
	char output_file_xml_temp[SS_MAXPATHLEN] = "";
	strcpy(output_file_xml_temp, temp_dir);
	strcat(output_file_xml_temp, "\\");
	strcat(output_file_xml_temp, xmlUid.c_str());
	strcat(output_file_xml_temp, ".xml");
	if (access(output_file_xml_temp, 0) == 0) {//存在
		if (remove(output_file_xml_temp) == 0) {
			cout << "exist" << output_file_xml_temp << "delete" << endl;
		}
	}
	POM_AM__set_application_bypass(true);
	ITKCALL(AE_export_named_ref(wlinfoXml, "XMLRendering", output_file_xml_temp));
	POM_AM__set_application_bypass(false);
	string path = output_file_xml_temp;
	//解析xml文件
	//创建一个XML结构并载入文件内容
	map<string, map<vector<string>, vector<string>>> xmlMap;//物料类型，<字段名，属性取值>
	string tableName = readXML(xmlMap, path);
	WriteLog("中间表：%s\n", tableName.c_str());
	//遍历map所有层级
	string revType = arg1value;
	vector<string> revTypeVec;
	Split(revType, ";", revTypeVec);
	int att_cnt = 0;
	tag_t *attachments = NULL;
	//获取根流程节点
	tag_t task_tag = msg.task;
	tag_t rootTask_tag = NULL;
	ifail = EPM_ask_root_task(task_tag, &rootTask_tag);
	vector<string> insertVec;
	vector<string> updateVec;
	vector<string> selectVec;
	vector<string> selectAfterUpdateVec;
	//获取目标引用对象
	ifail = EPM_ask_attachments(rootTask_tag, EPM_target_attachment, &att_cnt, &attachments);
	for (int i = 0; i < att_cnt; i++) {
		char *object_TYPE_1 = NULL;
		ifail = AOM_ask_value_string(attachments[i], "object_type", &object_TYPE_1);//对象类型
		WriteLog("当前类型对象为   %s\n", object_TYPE_1);
		string partType = object_TYPE_1;
		if (hasElement(revTypeVec, partType) == 0) {
			//
			string sqlStr = "insert into ";
			string updateStr = "update ";
			string selectStr = "select * from  ";
			string selectAfterUpdateStr = "select * from  ";
			string updateWhere = "";
			sqlStr = sqlStr.append(tableName).append(" (");
			selectStr = selectStr.append(tableName).append(" ");
			selectAfterUpdateStr = selectAfterUpdateStr.append(tableName).append(" ");
			string valueStr = " VALUES (";
			//包含类型,连接数据库
			if (log == false) {
				cout << "登陆成功" << endl;
				tag_t partItem = NULL;
				ITEM_ask_item_of_rev(attachments[i], &partItem);
				char *itemType = NULL;
				AOM_ask_value_string(partItem, "object_type", &itemType);
				string itemTypeString = itemType;
				map<vector<string>, vector<string>> propertyMap;
				propertyMap = xmlMap[itemType];
				if (propertyMap.size() == 0) {
					propertyMap = xmlMap["通用"];
				}
				map<vector<string>, vector<string>>::iterator rev_it2;
				for (rev_it2 = propertyMap.begin(); rev_it2 != propertyMap.end(); rev_it2++) {
					vector<string> nameVec = rev_it2->first;
					vector<string> valueVec = rev_it2->second;
					for (int j = 0; j < nameVec.size(); j++) {
						string columnName = nameVec[j];
						string columnValue = valueVec[j];
						WriteLog("字段名 %s, 取值  %s\n", columnName.c_str(), columnValue.c_str());
						WriteLog("字段名 %s, 取值  %s\n", columnName.c_str(), columnValue.c_str());
						sqlStr = sqlStr.append(columnName);
						if (strcmp(columnName.c_str(), "TRANSNO") == 0) {
							//时间已经处理，直接获取即可
							valueStr.append("'").append(columnValue).append("'");
							if (updateWhere.length() == 0) {
								updateWhere = updateWhere.append(" where ");
								updateWhere = updateWhere.append(columnName).append("='").append(columnValue).append("' and ");
								selectStr = selectStr.append(" where ");
								selectStr = selectStr.append(columnName).append("='").append(columnValue).append("' and ");
								selectAfterUpdateStr = selectAfterUpdateStr.append(" where ");
								selectAfterUpdateStr = selectAfterUpdateStr.append(columnName).append("='").append(columnValue).append("' and ");
							}
							else {
								updateWhere = updateWhere.append(columnName).append("='").append(columnValue).append("'");
								selectStr = selectStr.append(columnName).append("='").append(columnValue).append("'");
								selectAfterUpdateStr = selectAfterUpdateStr.append(columnName).append("='").append(columnValue).append("'");
							}
						}
						else if (strcmp(columnName.c_str(), "SESSIONID") == 0) {
							//固定值，直接获取即可
							valueStr.append("'").append(columnValue).append("'");
						}
						else if (strcmp(columnName.c_str(), "TRANSSTATUS") == 0) {
							//不做任何处理，但在传递完毕后更新
							updateStr = updateStr.append(tableName).append(" set ").append(columnName).append("='").append(columnValue).append("'  ");
								selectAfterUpdateStr = selectAfterUpdateStr.append(columnName).append("='").append(columnValue).append("' and ");
							valueStr.append("'").append(" ").append("'");
						}
						else if (strcmp(columnName.c_str(), "PUID") == 0) {
							//获取所有发布状态release_status_list
							char *puid = NULL;
							ITK__convert_tag_to_uid(attachments[i], &puid);
							string puidString = puid;
							valueStr.append("'").append(puid).append("'");
							if (updateWhere.length() == 0) {
								updateWhere = updateWhere.append(" where ");
								updateWhere = updateWhere.append(columnName).append("='").append(puid).append("' and ");
								selectStr = selectStr.append(" where ");
								selectStr = selectStr.append(columnName).append("='").append(columnValue).append("' and ");
								selectAfterUpdateStr = selectAfterUpdateStr.append(" where ");
								selectAfterUpdateStr = selectAfterUpdateStr.append(columnName).append("='").append(columnValue).append("' and ");
							}
							else {
								updateWhere = updateWhere.append(columnName).append("='").append(puid).append("'");
								selectStr = selectStr.append(columnName).append("='").append(puid).append("'");
								selectAfterUpdateStr = selectAfterUpdateStr.append(columnName).append("='").append(puid).append("'");
							}
							DOFREE(puid);
						}
						else {
							//其他情况获取属性
							vector<string> vec;
							if (columnValue.size() > 0) {
								Split(columnValue, ".", vec);
								char *tempValue = NULL;
								if (vec.size() == 2) {
									tag_t objTag = NULL;
									if (strcmp(vec[0].c_str(), "item") == 0) {
										objTag = partItem;
									}
									else if (strcmp(vec[0].c_str(), "rev") == 0) {
										objTag = attachments[i];
									}
									//需要注意，如果属性不存在或者说不准确，就传空值
							ITKCALL(ifail=		AOM_UIF_ask_value(objTag, vec[1].c_str(), &tempValue));
							
							removeQuotes(tempValue);

							string tempValueString = " ";
							if (ifail == 0) {
							
								tempValueString = tempValue;
							}else {
								showError = true;
								WriteLog("属性异常：%s\n", vec[1].c_str());
							}
							EMH_clear_errors();
							valueStr.append("'").append(tempValueString).append("'");
								}
								DOFREE(tempValue);
							}
							else {
								valueStr.append("' '");
							}
						}
						if (j < nameVec.size() - 1) {
							valueStr.append(",");
							sqlStr = sqlStr.append(",");
						}
						else {
							valueStr.append(")");
							sqlStr = sqlStr.append(") ");
						}
					}
				}
				sqlStr = sqlStr.append(valueStr);
				//正式系统编码utf-8,测试系统gbk
				updateStr = updateStr.append(updateWhere);
				sqlStr = Utf8ToGbk(sqlStr.c_str());
				updateStr = Utf8ToGbk(updateStr.c_str());
				selectStr= Utf8ToGbk(selectStr.c_str());
				selectAfterUpdateStr = Utf8ToGbk(selectAfterUpdateStr.c_str());
				WriteLog("gbk插入语句：%s\n", sqlStr.c_str());
				WriteLog("更新语句：%s\n", updateStr.c_str());
				WriteLog("查询语句：%s\n", selectStr.c_str());
				WriteLog("更新后查询语句：%s\n", selectAfterUpdateStr.c_str());
				insertVec.push_back(sqlStr);
				updateVec.push_back(updateStr);
				selectVec.push_back(selectStr);
				selectAfterUpdateVec.push_back(selectAfterUpdateStr);
				char sendChar[200] = "";
				strcpy(sendChar, sqlStr.c_str());
				char sendChar2[200] = "";
				strcpy(sendChar2, selectStr.c_str());
				int result = ado0.ado_QuerySQLNoInputParam(sendChar2);
				bool resultSql = ado0.executeInsert(sendChar2, sendChar, result);
			}
			else {
				cout << "登录失败" << endl;
			}
		}
		DOFREE(object_TYPE_1);
	}
	//更新数据库
	for (int i = 0; i < updateVec.size(); i++) {
		string updateSql = updateVec[i];
		string selectSql = selectVec[i];
		string insertSql = insertVec[i];
		string selectUpdate = selectAfterUpdateVec[i];
		char sendChar[200] = "";
		char sendChar2[200] = "";
		char sendChar3[200] = "";
		strcpy(sendChar, updateSql.c_str());
		strcpy(sendChar2, selectSql.c_str());
		strcpy(sendChar3, selectUpdate.c_str());
		int result = ado0.ado_QuerySQLNoInputParam(sendChar2);
		if (result==0) {
			showError = true;
			WriteLog("插入失败：%s\n", insertSql.c_str());
		}
		else {
			bool resultSql = ado0.execute2(sendChar2, sendChar, result);
			result = ado0.ado_QuerySQLNoInputParam(sendChar3);
			if (result == 0) {
				showError = true;
				WriteLog("更新失败：%s\n", updateSql.c_str());
			}
		}
	}
	ado0.close();
	//EMH_clear_errors();
	DOFREE(attachments);
	//if (showError == true) {
	//	string logName = "数据异常，详见服务器日志：";
	//	logName = logName.append(TC_LOG_FILE);
	//	EMH_store_error_s1(EMH_severity_warning, EMH_AE_error_base, logName.c_str());
	//}
	WriteLog("=========================================================\n");
	WriteLog("JD_ItemInfoToMediDatabase 结束\n");
	WriteLog("=========================================================\n");
	return 0;
}