/*
 * 这个触发器需要更新完历史数据后才能部署，
 * 一、删除时调用方法，传入OLD失单型号ID：
 * 		1、找到是这个失单型号的所有保有设备，删除掉；
 * 		2、这个需要做成共通方法，传进来失单报告，然后以便三、1使用；
 * 二、插入时调用方法，传入NEW失单型号：
 * 这个也需要写成共通方法，以供三、2使用；
 * 		1、前提：
 *    		1）失单型号的报告是失单报告或者部分失单报告；
 *    		2）失单型号的询价所在医院的记录类型是HP；
 * 		2、找到插入所有失单型号中有失单产品型号的数据；
 * 		3、根据数量生成保有设备，把这个保有设备的型号设置为这个保有设备；
 * 三、更新：
 * 		1、删除：
 * 			1）从有产品型号更新为无产品型号；
 *  		2）调用一的方法，删除掉保有设备；
 * 		2、插入：
 * 			1）从无产品型号更新为有产品型号；
 * 			2）调用二的方法插入数据；
 * 		3、更新：
 * 			1）如果产品或者数量发生了变化，而且符合失单型号对报告的需求；
 * 			2）调用四的方法更新保有设备；
 * 四、更新调用，传入New失单型号 list以及map;
 *		1、找到这个失单型号ID的所有失单保有设备；
 * 		2、循环每个失单保有设备的失单数量：
 * 			1）先用在失单数量下的保有设备，对比一下产品，有变化加入更新数据行列；
 * 			2）用完这个失单下的所有保有设备，插入失单设备；
 * 		3、循环完如果这个失单报告还有保有设备，记录下来以供删除；
 *		4、插入失单设备；
 *		5、更新设备；
 *		6、删除保有设备；
 * */
public without sharing class PCLLostProduct2AssetHandler extends Oly_TriggerHandler {
	private Map<Id, PCLLostProduct__c> newMap;
	private Map<Id, PCLLostProduct__c> oldMap;
	private List<PCLLostProduct__c> newList;
	private List<PCLLostProduct__c> oldList;
	public PCLLostProduct2AssetHandler() {
		this.newMap = (Map<Id, PCLLostProduct__c>) Trigger.newMap;
		this.oldMap = (Map<Id, PCLLostProduct__c>) Trigger.oldMap;
		this.newList = (List<PCLLostProduct__c>) Trigger.new;
		this.oldList = (List<PCLLostProduct__c>) Trigger.old;
	}
	protected override void afterUpdate() {
		updateProduct2Asset(newList,oldMap);
	}

	protected override void afterInsert() {
		insertLostAsset(newList);
	}
	protected override void beforedelete() {
		deleteLostAsset(oldMap.keySet());
	}

	private void deleteLostAsset( set<id> oldIDList){
		list<Asset> delAstList = new list<Asset>();
		if(oldIDList.size()> 0) {
			delAstList =
			[select id
			 from asset
			 where LostProduct__c in: oldIDList];
		}
		if(delAstList.size() > 0) {
			delete delAstList;
		}
	}

	private void insertLostAsset(List<PCLLostProduct__c> newList){
		list<asset> InsertAssetlist = new list<asset>();
		for (PCLLostProduct__c LostProduct : newList) {
			// 部分失单或失单报告型号而且询价上的医院真是医院
			if ((LostProduct.lcrRecordType_DevName__c == 'PCL_Lost_report' ||
			     LostProduct.lcrRecordType_DevName__c == 'PCL_PartLost_report'
			     ) && LostProduct.HP_RecordType_DevName__c == 'HP'
			    && string.isNotBlank(LostProduct.LostProduct__c))
			{
				for(integer i = 0; i <integer.valueof(lostProduct.Quantity__c); i++) {
					InsertAssetlist.add(buildAsset (lostProduct));
				}
			}
		}

		if(InsertAssetlist.size() > 0) {
			insert InsertAssetlist;
		}
	}
	private void updateProduct2Asset(List<PCLLostProduct__c> newList,
	                                 Map<Id, PCLLostProduct__c> oldMap){
		// 要被删除数据的ID的set
		set<id> oldDelIDList = new set<id>();
		// 要被插入的保有设备的失单型号的new的list
		list<PCLLostProduct__c> newInsertList =
			new list<PCLLostProduct__c>();
		//需要走更新流程的失单型号
		List<PCLLostProduct__c> newUpdateList =
			new List<PCLLostProduct__c>();
		//需要走更新流程的失单型号IDSet
		set<ID> newUpIDSet = new set<ID>();

		// for循环，判断哪些需要增加、删除或更新
		for( PCLLostProduct__c NewLsP : newList) {
			PCLLostProduct__c oldLsP = oldMap.get(NewLsP.id);
			//1、产品型号有值变为产品型号为空，需要删除；
			if(string.isNotBlank(oldLsP.LostProduct__c) &&
			   string.isBlank(NewLsP.LostProduct__c)) {
				oldDelIDList.add(NewLsP.id);
			}
			//2、产品型号为空变为产品型号有值，需要插入失单保有设备；
			if(string.isBlank(oldLsP.LostProduct__c) &&
			   string.isNotBlank(NewLsP.LostProduct__c)) {
				newInsertList.add(NewLsP);
			}
			// 3、如果
			//   1）新失单型号所在的报告是失单报告或者部分失单报告；
			//   2）所在询价的医院是医院
			//   3）失单型号产品不为空；
			//   4）产品更改或者数量更改；
			//  那么是需要更新的数据
			if ((NewLsP.lcrRecordType_DevName__c == 'PCL_Lost_report'
			     || NewLsP.lcrRecordType_DevName__c == 'PCL_PartLost_report'
			     ) && NewLsP.HP_RecordType_DevName__c == 'HP'
			    && string.isNotBlank(NewLsP.LostProduct__c)
			    && ( NewLsP.LostProduct__c != oldLsP.LostProduct__c
			         || NewLsP.Quantity__c != oldLsP.Quantity__c
			         )
			    )
			{
				newUpdateList.add(NewLsP);
				newUpIDSet.add(NewLsP.Id);
			}

		}

		// 删除数据
		if(oldDelIDList.size() > 0) {
			deleteLostAsset(oldDelIDList);
		}
		// 插入数据
		if(newInsertList.size()>0) {
			insertLostAsset(newInsertList);
		}
		// 更新数据
		if(newUpdateList.size()>0) {
			updateLsAHandler(newUpdateList,newUpIDSet);
		}

	}

	private void updateLsAHandler(List<PCLLostProduct__c> newList,set<Id> newIDSet) {

		//需要插入和更新的保有设备数据
		list<asset> upsertAstList = new List<asset>();

		//需要删除的保有设备数据
		list<asset> delAstList = new List<asset>();

		// 构建map，以便判断是否需要删除或者更新已有保有设备；
		map<id, list<asset> > LsPID2Asset = new map<id, list<asset> >();

		// 检索这个失单型号下面所有保有项目
		list<asset> oldAssetList = [
			select id, LostProduct__c, Product2Id,
			Status, Asset_Owner__c, IsCompetitorProduct
			from asset
			where LostProduct__c in : newIDSet
		];

		for(asset tempAst: oldAssetList) {
			list<asset> tempAstList = new List<asset>();
			if(LsPID2Asset.containsKey(tempAst.LostProduct__c)) {
				tempAstList = LsPID2Asset.get(tempAst.LostProduct__c);
			}
			tempAstList.add(tempAst);
			LsPID2Asset.put(tempAst.LostProduct__c, tempAstList);
		}
		// 循环现有失单型号，
		for(PCLLostProduct__c tempLsP : newList) {
			// 获取当前失单型号的所有失单保有设备
			list<asset> tempAstList = LsPID2Asset.get( tempLsP.id );
			for(integer i = 0; i < integer.valueOf(tempLsP.Quantity__c); i++) {
				asset tempAst = buildAsset(tempLsP);
				// 如果当前失单型号还有值，那么获取一个更新，否则就插入
				if(tempAstList !=null && tempAstList.size() > 0) {
					asset oldAst = tempAstList.remove(0);
					// 如果发生变化以后，才需要更新
					if(tempAst.Product2Id != oldAst.Product2Id ||
					   tempAst.Status != oldAst.Status ||
					   tempAst.Asset_Owner__c != oldAst.Asset_Owner__c ||
					   tempAst.IsCompetitorProduct != oldAst.IsCompetitorProduct
					   ) {
						tempAst.id = oldAst.id;
						upsertAstList.add(tempAst);
					}
				}
				else{
					upsertAstList.add(tempAst);
				}
			}
			// 如果还有多出来的，那么这些就是需要删除的失单保有设备
			if(tempAstList !=null && tempAstList.size()> 0) {
				delAstList.addAll(tempAstList);
			}
		}
		// 插入或者更新失单保有设备
		if(upsertAstList.size() > 0) {
			upsert upsertAstList;
		}
		// 删除多的失单保有设备
		if(delAstList.size() > 0) {
			delete delAstList;
		}
	}

	private asset buildAsset(PCLLostProduct__c LostProduct){
		Asset Ast = new Asset(
			Name = '*',
			// CHAN-CCR6MW gzw 【委托】【保有设备】保有设备发货日逻辑 start
			Posting_Date__c = Date.today(),
			// CHAN-CCR6MW gzw 【委托】【保有设备】保有设备发货日逻辑 end
			Product2Id = LostProduct.LostProduct__c,
			Opportunity__c = LostProduct.Opportunity__c,
			InstallDate = LostProduct.Submit_Day__c,
			Hospital__c = LostProduct.LostHP__c,
			Department_Class__c = LostProduct.LostDepartment_Class__c,
			AccountId = LostProduct.LostAccount__c,
			Status = '使用中',
			Asset_Owner__c = '病院資産',
			IsCompetitorProduct = True,
			LostProduct__c = LostProduct.id
			);
		return ast;
	}
}