public without sharing class FixtureDeliverySlipHandler extends Oly_TriggerHandler {
    private Map<Id, FixtureDeliverySlip__c> newMap;
    private Map<Id, FixtureDeliverySlip__c> oldMap;
    private List<FixtureDeliverySlip__c> newList;
    private List<FixtureDeliverySlip__c> oldList;


    public FixtureDeliverySlipHandler() {
        this.newMap = (Map<Id, FixtureDeliverySlip__c>) Trigger.newMap;
        this.oldMap = (Map<Id, FixtureDeliverySlip__c>) Trigger.oldMap;
        this.newList = (List<FixtureDeliverySlip__c>) Trigger.new;
        this.oldList = (List<FixtureDeliverySlip__c>) Trigger.old;
    }

    protected override void beforeInsert() {
        beforeSetValue();
    }

    protected override void beforeUpdate() {
        beforeSetValue();
    }

    protected override void afterInsert() {
        setRaMail();
        setCaMail();
    }

    protected override void afterUpdate() {
        setRaMail();
        setCaMail();
    }

    protected override void beforeDelete() {
        //运输单的删除Check
        //只在beforeDelete里执行
        checkDelete();
    }

    private void beforeSetValue() {
        for (FixtureDeliverySlip__c nObj : newList) {
            if (Trigger.isInsert == True) {
                nObj.DeliveryCompany_SlipNo__c = nObj.DeliveryCompany__c + ':' + nObj.Name + ':' + nObj.DeliveryType__c;
                nObj.CreatedBy_Name_Text__c = Userinfo.getLastName() + ' ' + Userinfo.getFirstName();
            }
            //分割合包信息字段
            if (String.isNotBlank(nObj.Combine_Pack__c)) {
                nObj.Combine_Pack_P1__c = nObj.Combine_Pack__c.left(250);
                nObj.Combine_Pack_P2__c = nObj.Combine_Pack__c.mid(250, 250);
                nObj.Combine_Pack_P3__c = nObj.Combine_Pack__c.mid(500, 250);
            }
        }
    }
    private void setCaMail() {
        Set<Id> fIdSet = new Set<Id>();
        Set<Id> returnfIdSet = new Set<Id>();
        for (FixtureDeliverySlip__c nObj : newList) {
            FixtureDeliverySlip__c oObj;
            if (Trigger.isUpdate) {
                oObj = oldMap.get(nObj.Id);
            }

            if (((Trigger.isInsert && nObj.Shippment_loaner_time__c != null) || (Trigger.isUpdate && oObj.Shippment_loaner_time__c != nObj.Shippment_loaner_time__c
                        && nObj.Shippment_loaner_time__c != null))) {
                if(nObj.DeliveryType__c == '发货'){
                    fIdSet.add(nObj.Id);
                }
                else if(nObj.DeliveryType__c == '回寄') {
                    returnfIdSet.add(nObj.Id);
                }
            }
        }
        if (!fIdSet.isEmpty()) {
            FixtureDeliverySlipHandler.setCaMailText(fIdSet, false);
        }
        if (!returnfIdSet.isEmpty()) {
            FixtureDeliverySlipHandler.setCaMailText(returnfIdSet, true);
        }
    }

    private void setRaMail() {
        Set<Id> fIdSet = new Set<Id>();
        for (FixtureDeliverySlip__c nObj : newList) {
            FixtureDeliverySlip__c oObj;
            if (Trigger.isUpdate) {
                oObj = oldMap.get(nObj.Id);
            }

            if (((Trigger.isInsert && nObj.Shippment_loaner_time__c != null) || (Trigger.isUpdate && oObj.Shippment_loaner_time__c != nObj.Shippment_loaner_time__c
                        && nObj.Shippment_loaner_time__c != null)) && nObj.DeliveryType__c == '发货') {
                fIdSet.add(nObj.Id);
            }
        }

        if (fIdSet.isEmpty()) {
            return;
        }
        FixtureDeliverySlipHandler.setRaMailText(fIdSet);
    }

    @future
    private static void setCaMailText(Set<Id> fIdSet, Boolean isReturn) {
        List<Consum_Apply_Equipment_Set_Detail__c> caesdList = [
                SELECT Fixture_Model_No__c
                     , SerialNumber_F__c
                     , Consum_Apply__c
                     , DeliverySlip__c
                     , Consum_Apply__r.Split_Apply_Reason__c
                FROM Consum_Apply_Equipment_Set_Detail__c
                WHERE (DeliverySlip__c IN:fIdSet OR Return_DeliverySlip__c IN:fIdSet)
                AND Cancel_Select__c = false
                ORDER BY Name
            ];
        Map<Id,Consum_Apply__c> caMap = new Map<Id,Consum_Apply__c>();
        String oCaId = '';
        String lastDeliveryId = '';
        Map<String, Integer> modelSnCategoryCntMap = new Map<String, Integer>();
        for (Consum_Apply_Equipment_Set_Detail__c caesd : caesdList) {
            if (String.isBlank(oCaId)) {
                oCaId = caesd.Consum_Apply__c;
            }
            if (oCaId != caesd.Consum_Apply__c) {
                Consum_Apply__c ca = createCa(oCaId, modelSnCategoryCntMap, lastDeliveryId, isReturn);
                caMap.put(oCaId, ca);
                modelSnCategoryCntMap = new Map<String, Integer>();
            }
            oCaId = caesd.Consum_Apply__c;
            lastDeliveryId = caesd.DeliverySlip__c;
            String model_sn_category = caesd.Fixture_Model_No__c + ',' + caesd.SerialNumber_F__c;
            if(isReturn) {
                model_sn_category += ',';
            }
            else if(caesd.Consum_Apply__r.Split_Apply_Reason__c == '到货NG分单') {
                model_sn_category += ',到货NG替换出库';
            }
            else {
                model_sn_category += ',正常出库';
            }
            Integer cnt = 1;
            if(modelSnCategoryCntMap.containsKey(model_sn_category)) {
                cnt = modelSnCategoryCntMap.get(model_sn_category) + 1;
            }
            modelSnCategoryCntMap.put(model_sn_category, cnt);
        }
        if (String.isNotBlank(oCaId)) {
            Consum_Apply__c ca = createCa(oCaId, modelSnCategoryCntMap, lastDeliveryId, isReturn);
            caMap.put(oCaId, ca);
        }
        update caMap.values();
    }

    @future
    private static void setRaMailText(Set<Id> fIdSet) {

        Map<Id, String> cpMap = new Map<Id, String>();
        Map<Id, Integer> dCntMap = new Map<Id, Integer>();

        List<Rental_Apply_Equipment_Set_Detail__c> raedss = [Select Id, Rental_Apply__c, Rental_Apply_Equipment_Set__r.Loaner_code_F__c, Rental_Apply__r.Notice_of_Delivery_Text__c, Rental_Apply_Equipment_Set__r.Rental_Apply__c,
                Rental_Apply__r.Shippment_ng_num__c, Rental_Apply__r.Rental_Apply_Equipment_Set_Cnt__c, DeliverySlip__r.Combine_Pack__c, DeliverySlip__r.DeliveryCompany__c, Rental_Apply_Equipment_Set__r.Yi_loaner_arranged__c,
                Rental_Apply_Equipment_Set__r.Received_NG_ReAssign__c, Rental_Apply_Equipment_Set__c, Canceled__r.Rental_Apply_Equipment_Set__r.Received_Confirm__c, Fixture_Model_No_text__c, ApplyPersonAppended_F__c,
                DeliverySlip__r.Name, Asset__r.SerialNumber
                From Rental_Apply_Equipment_Set_Detail__c
                Where DeliverySlip__c =: fIdSet
                Order by Rental_Apply__c, Rental_Apply_Equipment_Set__c, Rental_Apply_Equipment_Set__r.IndexFromUniqueKey__c, IndexFromUniqueKey__c];

        Map<Id,Map<Rental_Apply_Equipment_Set__c, List<Rental_Apply_Equipment_Set_Detail__c>>> raedsMap = new Map<Id,Map<Rental_Apply_Equipment_Set__c, List<Rental_Apply_Equipment_Set_Detail__c>>>();
        for (Rental_Apply_Equipment_Set_Detail__c raesd : raedss) {
            if (!raedsMap.containsKey(raesd.Rental_Apply__c)) {
                raedsMap.put(raesd.Rental_Apply__c, new Map<Rental_Apply_Equipment_Set__c, List<Rental_Apply_Equipment_Set_Detail__c>>());
                cpMap.put(raesd.Rental_Apply__c, raesd.DeliverySlip__r.Combine_Pack__c);
                dCntMap.put(raesd.Rental_Apply__c, 0);
            }

            if (!raedsMap.get(raesd.Rental_Apply__c).containsKey(raesd.Rental_Apply_Equipment_Set__r)) {
                raedsMap.get(raesd.Rental_Apply__c).put(raesd.Rental_Apply_Equipment_Set__r, new List<Rental_Apply_Equipment_Set_Detail__c>());
            }
            raedsMap.get(raesd.Rental_Apply__c).get(raesd.Rental_Apply_Equipment_Set__r).add(raesd);
            dCntMap.put(raesd.Rental_Apply__c, dCntMap.get(raesd.Rental_Apply__c) + 1);
        }
        if (!raedsMap.isEmpty()) {
            Map<Id, Rental_Apply__c> raMap = new Map<Id, Rental_Apply__c>();
            Map<Id, String> deliverySlipNameMap = new Map<Id, String>();
            Integer i = 0;
            for (Id raId :  raedsMap.keySet()) {
                for (Rental_Apply_Equipment_Set__c raes : raedsMap.get(raId).keySet()) {
                    if (!raMap.containsKey(raes.Rental_Apply__c)) {
                        i = 0;
                        raMap.put(raes.Rental_Apply__c, new Rental_Apply__c(Id = raes.Rental_Apply__c,
                                Combine_Pack__c = !cpMap.containsKey(raId) ? '' : cpMap.get(raId),
                                Assigned_Text__c = '具体明细：<BR>',
                                Notice_of_Delivery_Text__c = ('出库通知：<BR> 出库条数：'
                                                  + raedsMap.get(raId).size()
                                                  + '<BR>明细共：'+ dCntMap.get(raId) +'条。<BR>')));
                    }
                    i ++;
                    Rental_Apply__c ra = raMap.get(raes.Rental_Apply__c);
                    String message = ra.Assigned_Text__c;
                    message += '配套' + i + '：'
                            + raes.Loaner_code_F__c + '<BR>';
                    for (Rental_Apply_Equipment_Set_Detail__c raesd : raedsMap.get(raId).get(raes)) {
                        message += '&nbsp;&nbsp;&nbsp;&nbsp;' + raesd.Fixture_Model_No_text__c;
                        message += '&nbsp;&nbsp;&nbsp;&nbsp;机身号:' + raesd.Asset__r.SerialNumber;
                        if (raesd.ApplyPersonAppended_F__c) {
                            message += '&nbsp;&nbsp;&nbsp;' + '追加附属品出库';
                        } else if (raesd.Rental_Apply_Equipment_Set__r.Received_NG_ReAssign__c) {
                            message += '&nbsp;&nbsp;&nbsp;' + '到货NG替换出库';
                        } else {
                            message += '&nbsp;&nbsp;&nbsp;' + '正常出库';
                        }
                        if (deliverySlipNameMap.containsKey(raesd.Rental_Apply__c) == false) {
                            deliverySlipNameMap.put(raesd.Rental_Apply__c, '<BR>物流单号:' + raesd.DeliverySlip__r.Name + '<BR>' + '发货-物流公司:' + raesd.DeliverySlip__r.DeliveryCompany__c + '<BR>');
                        }
                        message += '<BR>';
                    }
                    ra.Assigned_Text__c = message;
                    raMap.put(raes.Rental_Apply__c, ra);
                }
            }
            for (Id raId : raMap.keySet()) {
                raMap.get(raId).Assigned_Text__c += deliverySlipNameMap.get(raId);
            }
            update raMap.values();
            return;
        }
    }

    //运输单的删除Check
    //只在beforeDelete里执行
    private void checkDelete() {
        //检索出所有和删除运输单关联的明细
        List<AggregateResult> g = [SELECT DeliverySlip__c, Return_DeliverySlip__c
                 FROM Rental_Apply_Equipment_Set_Detail__c
                WHERE (DeliverySlip__c =: oldList
                         OR Return_DeliverySlip__c =: oldList
                      )
                GROUP BY DeliverySlip__c, Return_DeliverySlip__c];
        if (g.isEmpty()) {
            return;
        }
        //有明细关联的运输单的IdSet
        Set<Id> fixtureDeliverySlipIdSet = new Set<Id>();
        //收集有明细关联的运输单号
        for (AggregateResult a : g) {
            Id deliverySlipId = (Id) a.get('DeliverySlip__c');
            Id deReturn_DeliverySlipId = (Id) a.get('Return_DeliverySlip__c');
            //发货运输单
            if (String.isNotBlank(deliverySlipId)) {
                fixtureDeliverySlipIdSet.add(deliverySlipId);
            }
            //回寄运输单
            if (String.isNotBlank(deReturn_DeliverySlipId)) {
                fixtureDeliverySlipIdSet.add(deReturn_DeliverySlipId);
            }
        }

        for (FixtureDeliverySlip__c fds : oldList) {
            //如果删除的运输单有明细关联报错不允许删除
            if (fixtureDeliverySlipIdSet.contains(fds.Id)) {
                fds.addError('有明细关联的运输单不能删除');
            }
        }
    }
    /**
    @description 发货和回寄邮件内容生成
    @param caId  耗材申请Id
    @param modelSnCategoryCntMap 型号,机身编辑,出库类别=>数量
    @param deliveryId 发货单或回寄单Id
    @param isReturn 是否是回寄单
    @return ca 待更新的耗材申请单
    */
    private static Consum_Apply__c createCa(Id caId, Map<String, Integer> modelSnCategoryCntMap
                                            , Id deliveryId, Boolean isReturn) {
        String message = '';
        for(String model_sn_category:modelSnCategoryCntMap.keySet()) {
            String model = model_sn_category.split(',', -1)[0];
            String sn = model_sn_category.split(',', -1)[1];
            String category  = model_sn_category.split(',' ,-1)[2];
            message += model + ' *' + modelSnCategoryCntMap.get(model_sn_category) + '\t';
            message += '机身编号:' + sn + '\t';
            message += category + '\n';
        }
        Consum_Apply__c ca = null;
        if (isReturn) {
            ca = new Consum_Apply__c( Id = caId, Return_Details_ForEmail__c = message, Return_Email_Time__c = System.Now());
        }
        else {
            ca = new Consum_Apply__c( Id = caId
                                    , Delivery_Detail_ForEmail__c = message
                                    , DeliverySlip__c = deliveryId
                                    );
        }
        return ca;
    }
    @TestVisible private static void test() {
        Integer i = 0;
        
    }
}