/*
* 这个触发器需要更新完历史数据后才能部署，
* 一、删除时调用方法，传入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 = '*',
                        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;
    }
}