@RestResource(urlMapping = '/SBG200/*')
global with sharing class SBG200Rest {

	global class GeDatas {
		public NFMUtil.Monitoring Monitoring;
		public GeData[] Partners;
	}

	//合作伙伴抬头层级
	global class GeData {
		public License_Info[] License_Info;

		public String CompanyCode;		//公司代码
		public Boolean IfControl;		//是否严格管控
	}

	//证照层级
	global class License_Info {
		public Detail_Info[] Detail_Info;

		public String LicenseType;		//证照类型
		public String BusLicenseNo;		//证照号
		public String ValidFrom;		//期限效期从
		public String ValidTo;			//期限效期至
	}
	//证照明细层级
	global class Detail_Info {

		public String ProName;			//装置名称
		public String ProSerial;		//辐射产品系列
		public String Quantity;			//数量
		public String Category;			//活动种类

	}


	@HttpPost
	global static void execute() {
		// 取得接口传输内容
		String strData = RestContext.request.requestBody.toString();
		GeDatas ges = (GeDatas) JSON.deserializeStrict(strData, GeDatas.class);

		if (ges == null ) {
			return;
		}

		NFMUtil.Monitoring Monitoring = ges.Monitoring;
		if (Monitoring == null) {
			return;
		}

		BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'SBG200', ges.Partners);
		if (String.isBlank(rowData.Log__c) == false) {
			executefuture(rowData.Id);
		}
		// JSONを戻す
		RestResponse res = RestContext.response;
		res.addHeader('Content-Type', 'application/json');
		res.statusCode = 200;
		String jsonResponse = '{"status": "0", "Message":""}';
		res.responseBody = blob.valueOf(jsonResponse);
		return;
	}

	@future
	global static void executefuture(String rowData_Id) {
		main(rowData_Id);
	}

	global static void main(String rowData_Id) {
		Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
		BatchIF_Log__c rowData = [Select Id, Name, Log__c, ErrorLog__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c, Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c, MessageGroupNumber__c, retry_cnt__c from BatchIF_Log__c where RowDataFlg__c = true and Id = :rowData_Id];
		String logstr = rowData.MessageGroupNumber__c + ' start\n';
		BatchIF_Log__c iflog = new BatchIF_Log__c();
		iflog.Type__c = 'SBG200';
		iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
		iflog.Log__c = logstr;
		iflog.ErrorLog__c = '';
		insert iflog;

		String rowDataStr = NFMUtil.getRowDataStr(rowData);
		List<GeData> geDataList = (List<GeData>) JSON.deserialize(rowDataStr, List<GeData>.class);
		if (geDataList == null || geDataList.size() == 0) {
			return;
		}

		//证照转换表
		Map<String, String> transferLicenseTypeMap = NFMUtil.BatchIF_Transfer('License_Information__c');
		//证照明细转换表
		Map<String, String> certificationDetailTransferMap = NFMUtil.BatchIF_Transfer('CertificationDetails__c');

		Savepoint sp = Database.setSavepoint();
		try {

			List<GeData> satisfyGeDataList = SatisfyGeData(geDataList, iflog);

			if ( satisfyGeDataList.size() > 0) {

				Map<String, Account> accountMap = existAccountMap(satisfyGeDataList);

				if ( accountMap.size() > 0 ) {

					deleteAccountLicenseInformation(accountMap);

					insertLicense_Information(satisfyGeDataList, accountMap, transferLicenseTypeMap, iflog, certificationDetailTransferMap);
				} else {

				}
			}

			logstr += '\nend';
			rowData.retry_cnt__c = 0;

		} catch (Exception ex) {

			Database.rollback(sp);
			System.debug(Logginglevel.ERROR, 'SBG200_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
			System.debug(Logginglevel.ERROR, 'SBG200_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
			logstr += '\n' + ex.getMessage();
			iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;

			if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
			if (rowData.retry_cnt__c < batch_retry_max_cnt) {
				rowData.retry_cnt__c++;
				LogAutoSendSchedule.assignOneMinute();
			}
			if (rowData.retry_cnt__c >= batch_retry_max_cnt) {
				rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c + '错误次数已经超过自动收信设定的最大次数，请手动收信';
			}
		}

		update rowData;
		iflog.Log__c = logstr;
		if (iflog.Log__c.length() > 131072) {
			iflog.Log__c = iflog.Log__c.subString(0, 131065) + ' ...';
		}
		if (iflog.ErrorLog__c.length() > 32768) {
			iflog.ErrorLog__c = iflog.ErrorLog__c.subString(0, 32760) + ' ...';
		}
		update iflog;
	}

	public static void insertLicense_Information(List<GeData> satisfyGeDataList, Map<String, Account> existAccountMap,
	        Map<String, String> transferLicenseTypeMap, BatchIF_Log__c iflog, Map<String, String> certificationDetailTransferMap) {

		System.debug('insertLicense_Information--->Start');

		Map<String, License_Info> satisfyLicenseInfoMap = new Map<String, License_Info>();
		//Boolean ifControl = false;
		Map<String,GeData> geDatalMap = new  Map<String,GeData>();
		for (GeData gedata : satisfyGeDataList) {
			geDatalMap.put(gedata.CompanyCode,gedata);
			//ifControl = gedata.IfControl;
			//System.label.IfControlRadiation = gedata.IfControl;
			for (License_Info licenseInfo : gedata.License_Info) {

				if (String.isBlank(licenseInfo.LicenseType) || String.isBlank(licenseInfo.BusLicenseNo) ||
				        String.isBlank(licenseInfo.ValidFrom) || String.isBlank(licenseInfo.ValidTo)) {
					continue;
				}

				String companyCodes = gedata.CompanyCode + ';' + licenseInfo.LicenseType;
				satisfyLicenseInfoMap.put(companyCodes, licenseInfo);
			}
		}

		if ( satisfyLicenseInfoMap.size() > 0 ) {

			List<License_Information__c> licenseInformationList = new List<License_Information__c>();
			List<CertificationDetails__c>  certificationDetailsList = new List<CertificationDetails__c>();
			Map<String, List<CertificationDetails__c>> LicenseDetailsMap = new Map<String, List<CertificationDetails__c>>();

			for (String companyCodes : satisfyLicenseInfoMap.keySet()) {

				License_Info license = satisfyLicenseInfoMap.get(companyCodes);
				String companyCode = companyCodes.split(';')[0];

				String licenseType =  FieldTransformation(companyCode, transferLicenseTypeMap, 'LicenseType__c', license.LicenseType, iflog, 'LicenseType');

				if (licenseType.equals('Invalid')) {
					continue;
				}

				License_Information__c  licenseInformation = new License_Information__c();
				licenseInformation.LicenseType__c = licenseType ;
				licenseInformation.BusinessLicense__c = license.BusLicenseNo ;
				licenseInformation.ValidFrom__c = NFMUtil.parseStr2Date(license.ValidFrom, false) ;
				licenseInformation.ValidTo__c = NFMUtil.parseStr2Date(license.ValidTo, false) ;
				licenseInformation.LicenseAndAccount__c = existAccountMap.get(companyCode).Id;
				licenseInformation.Name = existAccountMap.get(companyCode).Name + licenseType;
				//辐射安全许可证
				if ( license.LicenseType == '08' && license.Detail_Info != null) {
					licenseInformation.IfControl__c = geDatalMap.get(companyCode).IfControl;
					LicenseDetailsMap.putAll(SatisfyLicenseDetailsMap(companyCode, license.Detail_Info, certificationDetailTransferMap, iflog));
				}

				licenseInformationList.add(licenseInformation);
			}

			if ( licenseInformationList.size() > 0 ) {

				upsert licenseInformationList;

				if ( LicenseDetailsMap.size() > 0) {

					insertCertificationDetail(LicenseDetailsMap, licenseInformationList);
				}
			}
		}

		System.debug('insertLicense_Information--->End');
	}
	//保存证照明细
	public static void insertCertificationDetail (Map<String, List<CertificationDetails__c>> LicenseDetailsMap,
	        List<License_Information__c> licenseInformationList) {

		System.debug('insertCertificationDetail--->Start');
		System.debug('LicenseDetailsMap---->' + LicenseDetailsMap);
		List<String> licenseInformationIdList = new List<String>();
		for (License_Information__c licenseInformation : licenseInformationList) {

			if ( licenseInformation.LicenseType__c == '辐射安全许可证' ) {

				licenseInformationIdList.add(licenseInformation.Id);
			}
		}
		System.debug('licenseInformationIdList----->' + licenseInformationIdList);
		List<License_Information__c> existList = [select id, Name, LicenseAndAccount__r.ManagementCode_Ext__c
		        from License_Information__c where Id In :licenseInformationIdList];
		Map<String, License_Information__c> existLicenseInformationMap = new Map<String, License_Information__c>();
		System.debug('existList---->' + existList);
		for (License_Information__c licenseInformation : existList) {

			String accountManagementCode = licenseInformation.LicenseAndAccount__r.ManagementCode_Ext__c;
			existLicenseInformationMap.put(accountManagementCode, licenseInformation);
		}
		System.debug('existLicenseInformationMap---->' + existLicenseInformationMap);
		List<CertificationDetails__c> insertCertificationDetailList = new List<CertificationDetails__c>();
		for ( String companyCode : LicenseDetailsMap.keySet()) {

			for ( CertificationDetails__c certificationDetail : LicenseDetailsMap.get(companyCode)) {

				if (existLicenseInformationMap.containsKey(companyCode)) {

					certificationDetail.LicenseInformation__c = existLicenseInformationMap.get(companyCode).Id;
					insertCertificationDetailList.add(certificationDetail);
				}

			}
		}
		System.debug('insertCertificationDetailList----->' + insertCertificationDetailList);

		if (insertCertificationDetailList.size() > 0) {

			upsert insertCertificationDetailList;
		}


		System.debug('insertCertificationDetail--->End');
	}

	//获取符合的证照明细,并给证照明细赋值
	public static Map<String, List<CertificationDetails__c>> SatisfyLicenseDetailsMap(String  companyCode,
	        List<Detail_Info> licenseDetailS, Map<String, String> certificationDetailTransferMap, BatchIF_Log__c iflog) {

		System.debug('SatisfyLicenseDetailsMap--->Start');
		Map<String, CertificationDetails__c> certificationDetailMap = new Map<String, CertificationDetails__c>();
		Map<String, List<CertificationDetails__c>> result = new Map<String, List<CertificationDetails__c>>();
		List<CertificationDetails__c> certificationDetailList = new List<CertificationDetails__c>();
		for (Detail_Info detailInfo : licenseDetailS) {

			if (String.isBlank(detailInfo.ProSerial) || String.isBlank(detailInfo.Quantity) ||
			        String.isBlank(detailInfo.Category)  ) {

				continue;
			}

			String licenseType =  FieldTransformation(companyCode, certificationDetailTransferMap, 'ProdustionType__c', detailInfo.ProSerial, iflog, 'ProSerial');
			if (licenseType.equals('Invalid')) {
				continue;
			}
			//String licenseType =  FieldTransformation(bpCode, certificationDetailTransferMap, 'ProductModel__c', detailInfo.ProSerial, iflog, 'ProSerial');
			Integer quantity = Integer.valueof(detailInfo.Quantity);
			String  remarks = detailInfo.ProName + '(' + quantity + ')';
			String key = licenseType + '-' + detailInfo.Category;
			if (!certificationDetailMap.containsKey(key)) {

				//CertificationDetails__c detail = new CertificationDetails__c();
				//detail.ProductModel__c = licenseType;
				//detail.ProductModelNumber__c = Integer.valueOf(detailInfo.Quantity);
				//detail.ActivitieTypes__c = detailInfo.Category;
				//detail.DeviceName__c = detailInfo.ProName;
				CertificationDetails__c detail = new CertificationDetails__c();
				detail.ProdustionType__c = licenseType;
				detail.ProductModelNumber__c = quantity;
				detail.ActivitieTypes__c = detailInfo.Category;
				detail.DeviceName__c = detailInfo.ProName;
				detail.Remarks__c = remarks;
				certificationDetailMap.put(key, detail);
			} else {
				certificationDetailMap.get(key).ProductModelNumber__c += quantity;
				certificationDetailMap.get(key).DeviceName__c += '/' + detailInfo.ProName;
				certificationDetailMap.get(key).Remarks__c += '/' + remarks;

			}
			
		}
		if ( certificationDetailMap.size() > 0 ) {
			for (CertificationDetails__c detail : certificationDetailMap.values()) {
				//result.add(detail);
				certificationDetailList.add(detail);
			}
		}

		result.put(companyCode, certificationDetailList);
		System.debug('SatisfyLicenseDetailsMap--->End');
		return result;
	}

	public static Map<String, Account> existAccountMap(List<GeData> satisfyGeDataList) {

		System.debug('existAccountMap--->Start');
		//更新客户，同时获取客户的编码和Id
		Map<String, Account> result = new Map<String, Account>();
		Map<String, GeData> companyCodeMap = new Map<String, GeData>();

		for (GeData gedata : satisfyGeDataList) {

			companyCodeMap.put(geData.CompanyCode, gedata);
		}

		List<Account> existAccountList = [select Id, Name, ManagementCode_Ext__c
		                                  from Account where ManagementCode_Ext__c In :companyCodeMap.keySet()];
		if ( existAccountList.size() > 0) {

			for (Account account : existAccountList) {

				//if (companyCodeMap.containsKey(account.ManagementCode_Ext__c)) {

				//	//更新客户"是否严格管控"字段
				//	account.IfControl__c = companyCodeMap.get(account.ManagementCode_Ext__c).IfControl;
				//}

				result.put(account.ManagementCode_Ext__c, account);
			}

			//upsert existAccountList;
		}
		System.debug('existAccountMap--->End');
		return result;
	}

	public static List<GeData> SatisfyGeData( List<GeData> geDataList, BatchIF_Log__c iflog) {

		List<GeData> result = new List<GeData>();
		for (GeData geData : geDataList) {

			if (String.isBlank(geData.CompanyCode)) {

				iflog.ErrorLog__c += 'CompanyCode of is required,This data is skipped.\n';
				continue;
			}

			if (gedata.License_Info == null) {
				continue;
			}

			result.add(geData);
		}

		return result;
	}

	//转换前后的值的对比
	public static String FieldTransformation(String bpCode, Map<String, String> transformation, String api, String toConvertStr, BatchIF_Log__c iflog, String receivesField ) {
		String afterTransformation = NFMUtil.getMapValue(transformation, api, toConvertStr, iflog);

		if (String.isNotBlank(afterTransformation) && !afterTransformation.equals(toConvertStr)) {

			return afterTransformation;
		}  else if (String.isNotBlank(afterTransformation) && afterTransformation.equals(toConvertStr)) {
			return afterTransformation;
		} else {

			iflog.ErrorLog__c += 'BPCode[ ' + bpCode + ' ] of ' + receivesField + ' [ ' + toConvertStr + ' ]' + ' is  Invalid,This data is skipped.\n';
			return 'Invalid';
		}
	}

	public static void deleteAccountLicenseInformation(Map<String, Account> accountMap) {

		System.debug('deleteAccountLicenseInformation--->Start');
		List<License_Information__c> existList = [select id, Name, AccountManagementCode__c,Is_Active_Formula__c 
		        from License_Information__c where AccountManagementCode__c In :accountMap.keySet() and Is_Active_Formula__c = true];

		if (existList.size() > 0) {
			delete existList;
		}
		System.debug('deleteAccountLicenseInformation--->End');
	}
}