public without sharing class AgencyOpportunityHandler extends Oly_TriggerHandler {

    private Map<Id, Agency_Opportunity__c> newMap;
    private Map<Id, Agency_Opportunity__c> oldMap;
    private List<Agency_Opportunity__c> newList;
    private List<Agency_Opportunity__c> oldList;

    private static Map<String, Id> product_CategoryMap = new Map<String, Id>();
    private static final String PRODUCT_CATEGORYERRORMESSAGE = '选择的产品区分 {0} 不存在';
    private static final String NEEDAPPLYRECORDTYPEID = Schema.SObjectType.Agency_Opportunity__c.getRecordTypeInfosByDeveloperName().get('Opportunity').getRecordTypeId();
    private static User loginUser {
        get{
            if(loginUser == null) {
                loginUser = [SELECT Id,
                                    ContactId,
                                    Contact.AccountId
                               FROM User
                              WHERE Id = :UserInfo.getUserId()];
            }
            return loginUser;
        }
        set{}
    }

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

    protected override void beforeInsert() {
        setproduct_CategoryMap();
        beforeExecute();
    }

    protected override void beforeUpdate() {
        setproduct_CategoryMap();
        beforeExecute();
    }

    protected override void afterInsert() {
        afterExecute();
        shareAgency_Opportunity_ToRole(this.newList);
        shareToOSCM();
    }

    protected override void afterUpdate() {
        shareToOSCM();
    }

    protected override void afterUndelete() {
        shareAgency_Opportunity_ToRole(this.newList);
    }
    /**
     * @description 设置product_CategoryMap并check选择的产品区分是否存在
     */
    private void setproduct_CategoryMap() {
        Map<String, Set<Agency_Opportunity__c>> product_CategoryIdMap = new Map<String, Set<Agency_Opportunity__c>>();
        Map<String, Agency_Opportunity__c> aoMap = new Map<String, Agency_Opportunity__c>();
        for (Agency_Opportunity__c nObj : newList) {

            if (String.isNotBlank(nObj.Product_Category1_P__c)
                    && !product_CategoryMap.containsKey(nObj.Product_Category1_P__c)) {
                if (!product_CategoryIdMap.containsKey(nObj.Product_Category1_P__c)) {
                    product_CategoryIdMap.put(nObj.Product_Category1_P__c, new Set<Agency_Opportunity__c>());
                }
                product_CategoryIdMap.get(nObj.Product_Category1_P__c).add(nObj);
            }

            if (String.isNotBlank(nObj.Product_Category2_P__c)
                    && !product_CategoryMap.containsKey(nObj.Product_Category2_P__c)) {
                if (!product_CategoryIdMap.containsKey(nObj.Product_Category2_P__c)) {
                    product_CategoryIdMap.put(nObj.Product_Category2_P__c, new Set<Agency_Opportunity__c>());
                }
                product_CategoryIdMap.get(nObj.Product_Category2_P__c).add(nObj);
            }

            if (String.isNotBlank(nObj.Product_Category3_P__c)
                    && !product_CategoryMap.containsKey(nObj.Product_Category3_P__c)) {
                if (!product_CategoryIdMap.containsKey(nObj.Product_Category3_P__c)) {
                    product_CategoryIdMap.put(nObj.Product_Category3_P__c, new Set<Agency_Opportunity__c>());
                }
                product_CategoryIdMap.get(nObj.Product_Category3_P__c).add(nObj);
            }
        }
        if (product_CategoryIdMap.size() > 0) {
            List<ProductTypes__c> pts = [SELECT Id, Name2__c
                                           FROM ProductTypes__c
                                          WHERE Name2__c = :product_CategoryIdMap.keySet()];
            for (ProductTypes__c pt : pts) {
                product_CategoryMap.put(pt.Name2__c, pt.Id);
                product_CategoryIdMap.remove(pt.Name2__c);
            }
            if (product_CategoryIdMap.size() > 0) {
                for (String ptName : product_CategoryIdMap.keySet()) {
                    for (Agency_Opportunity__c ao : product_CategoryIdMap.get(ptName)) {
                        ao.addError(String.format(PRODUCT_CATEGORYERRORMESSAGE, new String[] {ptName}));
                    }
                }
            }
        }
    }

    // 设 deptRectMap
    private void beforeExecute() {
        Set<Id> ahId = new Set<Id>();
        Set<Id> opportunitySet = new Set<Id>();
        List<Agency_Opportunity__c> isChangedAgencyIDList = new List<Agency_Opportunity__c>();
        // vivek update 2019-11-04 担当问题 经销商医院市 科室分类 start
        Set<Id> salesBearId = new Set<Id>();
        Set<Id> hospitalId  = new Set<Id>();
        Set<Id> ocsmOppId = new Set<Id>();
        for(Agency_Opportunity__c nObj : newList){
            salesBearId.add(nObj.Agency_Person__c);
            hospitalId.add(nObj.Agency_Hospital__c);
            ocsmOppId.add(nObj.Change_To_Opportunity__c);

        }
        Map<String,String> salesBearNameMap = new Map<String,String>();
        Map<String,String> hospitalCityMap = new Map<String,String>();
        // Map<String,String> ocsmOppMap = new Map<String,String>();
        Map<String,Opportunity> ocsmOppMap = new Map<String,Opportunity>();
        List<Contact> conList = [select id,name from Contact where id = :salesBearId];
        List<Agency_Hospital_Link__c> agenhlList = [select id,Hospital_City_Master__c from Agency_Hospital_Link__c where id = :hospitalId];
        List<Opportunity> ocsmOppList = [select id,Name,Strategic_department_Class_Name__c,Opportunity_No__c from Opportunity where id = :ocsmOppId];
        for(Contact con :conList){
            salesBearNameMap.put(con.id, con.name);
        }
        for(Agency_Hospital_Link__c agenhl :agenhlList){
            hospitalCityMap.put(agenhl.Id, agenhl.Hospital_City_Master__c);
        }
        for(Opportunity ocsmOpp : ocsmOppList){
            // ocsmOppMap.put(ocsmOpp.Id, ocsmOpp.Strategic_department_Class_Name__c);
            ocsmOppMap.put(ocsmOpp.Id, ocsmOpp);
        }
        // vivek update 2019-11-04 担当问题 经销商医院市 科室分类 end
        for(Agency_Opportunity__c nObj : newList) {
            Agency_Opportunity__c oObj = null;
            // vivek update 2019-11-04 担当问题 经销商医院市 科室分类 start
            if(salesBearNameMap.containsKey(nObj.Agency_Person__c)){
                nObj.Agency_PersonName__c = salesBearNameMap.get(nObj.Agency_Person__c);
            }
            if(hospitalCityMap.containsKey(nObj.Agency_Hospital__c)){
                nObj.Hospital_City_Master__c = hospitalCityMap.get(nObj.Agency_Hospital__c);
            }
            if(ocsmOppMap.containsKey(nObj.Change_To_Opportunity__c)){
                nObj.Strategic_department_Class_Name__c = ocsmOppMap.get(nObj.Change_To_Opportunity__c).Strategic_department_Class_Name__c;
                nObj.Change_To_Opportunity_T__c = ocsmOppMap.get(nObj.Change_To_Opportunity__c).Name;
                nObj.OCSM_Opportunity_No__c = ocsmOppMap.get(nObj.Change_To_Opportunity__c).Opportunity_No__c;
            }
            // vivek update 2019-11-04 担当问题 经销商医院市 科室分类 end
            if (oldMap != null && oldMap.containsKey(nObj.Id)) {
                oObj = oldMap.get(nObj.Id);
                if (oObj.OCM_Change_To_Opportunity_Flg__c == true && nObj.OCM_Change_To_Opportunity_Flg__c == false) {
                    opportunitySet.add(oObj.Change_To_Opportunity__c);
                    nObj.Change_To_Opportunity__c = null;
                }
                else if (String.isBlank(oObj.Change_To_Opportunity__c) == false && String.isBlank(nObj.Change_To_Opportunity__c) == true) {
                    opportunitySet.add(oObj.Change_To_Opportunity__c);
                    nObj.OCM_Change_To_Opportunity_Flg__c = false;
                }
            }

            if (String.isNotBlank(nObj.Product_Category1_P__c)) {
                nObj.Product_Category1__c = product_CategoryMap.get(nObj.Product_Category1_P__c);
            }
            if (String.isNotBlank(nObj.Product_Category2_P__c)) {
                nObj.Product_Category2__c = product_CategoryMap.get(nObj.Product_Category2_P__c);
            }
            if (String.isNotBlank(nObj.Product_Category3_P__c)) {
                nObj.Product_Category3__c = product_CategoryMap.get(nObj.Product_Category3_P__c);
            }

            if (nObj.Agency__c != null && String.isBlank(nObj.Owner_Agency_ID__c)) {
                List<User> owners = [select Id from User where AccountId =:nObj.Agency__c and isActive = true and Contact.Agency_User__c = true order by CreatedDate limit 1];
                if (owners.size() <= 0) {
                    // 20230605 gzw 跳过验证
                    // nObj.addError('该经销商不存在客户人员，请修改');
                } else {
                    User owner = owners[0];
                    if (String.isNotBlank(loginUser.Contact.AccountId)
                            || (nObj.NewOpportunity_Agency_Apply_Status__c == '批准'
                                && oObj != null && oObj.NewOpportunity_Agency_Apply_Status__c != '批准')
                            // Gzw SWAG-BGTBNS 2019/10/10 目标没有审批，但是需要做共享
                            || nObj.RecordType_Name__c == 'Target'
                    ) {
                        nObj.OwnerId = owner.Id;
                        nObj.Agency_ID__c = String.valueOf(nObj.Agency__c).substring(0,15);
                        if (Trigger.isUpdate) isChangedAgencyIDList.add(nObj);
                    }
                }
            } else {
                nObj.Agency__c = nObj.Owner_Agency_ID__c;
                if (String.isNotBlank(loginUser.Contact.AccountId)
                        || (nObj.NewOpportunity_Agency_Apply_Status__c == '批准'
                            && oObj != null && oObj.NewOpportunity_Agency_Apply_Status__c != '批准')
                ) {
                    nObj.Agency_ID__c = String.valueOf(nObj.Owner_Agency_ID__c).substring(0,15);
                    if (Trigger.isUpdate) isChangedAgencyIDList.add(nObj);
                }
            }
            if (nObj.Agency_Hospital__c != null) {
               ahId.add(nObj.Agency_Hospital__c);
               nObj.Agency_Hospital_All__c = nObj.Agency_Hospital__c;
            } else if (nObj.Agency_Hospital_Target__c != null) {
               nObj.Agency_Hospital_All__c = nObj.Agency_Hospital_Target__c;
            }
            if (nObj.Department_Cateogy_l__c == null && nObj.Department_Cateogy__c != null) {
                if (nObj.Department_Cateogy__c == 'GI' || nObj.Department_Cateogy__c == 'BF') {
                    nObj.Department_Cateogy_l__c = 'GIR';
                } else if (nObj.Department_Cateogy__c == 'ET') {
                    nObj.Department_Cateogy_l__c = 'ET';
                } else {
                    nObj.Department_Cateogy_l__c = 'SP';
                }
            }

            if (String.isNotBlank(nObj.Change_To_Opportunity__c)
                    && Trigger.isInsert
                    && String.isBlank(loginUser.Contact.AccountId)) {
                nObj.OwnerId = nObj.OCSM_Opportunity_OwnerId__c;
            }

            nObj.Sales_Manager__c = nObj.Sales_Manager_F__c;
            if (Trigger.isInsert
                    && nObj.RecordTypeId == NEEDAPPLYRECORDTYPEID
                    && String.isBlank(loginUser.Contact.AccountId)
                    && (String.isBlank(nObj.NewOpportunity_Agency_Apply_Status__c)
                            || nObj.NewOpportunity_Agency_Apply_Status__c == '草案中')) {
                nObj.NewOpportunity_Agency_Apply_Status__c = '填写完毕';
            }
            if (false == nObj.Name.startsWith('::')) {
                nObj.Name = '::' +nObj.Name;
            }
            
        }
        if (isChangedAgencyIDList.size() > 0) {
            shareAgency_Opportunity_ToRole(isChangedAgencyIDList);
        }

        // FIXME develoerNameより
        /*20230214 you  DB202302187947 101去掉一个sql
        String[] deptTypes = new String[] {'Department_Class_OTH', 'Department_Class_BF', 'Department_Class_GYN', 'Department_Class_GS', 'Department_Class_URO', 'Department_Class_GI', 'Department_Class_ENT', 'Department_Class_ET'};
        List<RecordType> deptRects = [select Id, DeveloperName from RecordType where IsActive = true and SobjectType = 'Account' and DeveloperName IN :deptTypes];
        Map<String, String> deptRectMap = new Map<String, String>();
        for (RecordType rect : deptRects) {
            String recordType = rect.DeveloperName;
            if (recordType == 'Department_Class_OTH') {
                deptRectMap.put('OTH', rect.Id);
            } else if (recordType == 'Department_Class_BF') {
                deptRectMap.put('BF', rect.Id);
            } else if (recordType == 'Department_Class_GYN') {
                deptRectMap.put('GYN', rect.Id);
            } else if (recordType == 'Department_Class_GS') {
                deptRectMap.put('GS', rect.Id);
            } else if (recordType == 'Department_Class_URO') {
                deptRectMap.put('URO', rect.Id);
            } else if (recordType == 'Department_Class_GI') {
                deptRectMap.put('GI', rect.Id);
            } else if (recordType == 'Department_Class_ENT') {
                deptRectMap.put('ENT', rect.Id);
            } else if (recordType == 'Department_Class_ET') {
                deptRectMap.put('ET', rect.Id);
            }
        }
        */
        //添加新逻辑 start
        String[] deptTypes = new String[] {'Department_Class_OTH', 'Department_Class_BF', 'Department_Class_GYN', 'Department_Class_GS', 'Department_Class_URO', 'Department_Class_GI', 'Department_Class_ENT', 'Department_Class_ET'};
        Map<String, String> deptRectMap = new Map<String, String>();
        Map<String, Schema.RecordTypeInfo> deptrectAllMap = Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName();
        for (string rect : deptTypes) {
            ID accid=deptrectAllMap.get(rect).getRecordTypeId();
            if (rect == 'Department_Class_OTH') {
                deptRectMap.put('OTH', accid);
            } else if (rect == 'Department_Class_BF') {
                deptRectMap.put('BF', accid);
            } else if (rect == 'Department_Class_GYN') {
                deptRectMap.put('GYN', accid);
            } else if (rect == 'Department_Class_GS') {
                deptRectMap.put('GS', accid);
            } else if (rect == 'Department_Class_URO') {
                deptRectMap.put('URO', accid);
            } else if (rect == 'Department_Class_GI') {
                deptRectMap.put('GI', accid);
            } else if (rect == 'Department_Class_ENT') {
                deptRectMap.put('ENT', accid);
            } else if (rect == 'Department_Class_ET') {
                deptRectMap.put('ET', accid);
            }
        }
         //添加新逻辑 end

        Map<Id, Id> ahMap = new Map<Id, Id>();
        List<Agency_Hospital_Link__c> ahlist = [select Id, Hospital__c from Agency_Hospital_Link__c where Id in :ahId];
        for (Agency_Hospital_Link__c ah : ahlist) {
            ahMap.put(ah.Id, ah.Hospital__c);
        }

        Map<String, Account> dcMap = new Map<String, Account>();
        List<Account> dcList = [select Id, RecordTypeId, Name, Hospital_Department_Class__c, OwnerId from account where Hospital_Department_Class__c in :ahMap.values() and RecordTypeId in :deptRectMap.values()];
        for (Account dc : dcList) {
            String key = String.valueof(dc.Hospital_Department_Class__c) + String.valueof(dc.RecordTypeId);
            dcMap.put(key, dc);
        }

        for(Agency_Opportunity__c nObj : newList) {
            if (nObj.Agency_Hospital__c != null) {
                String hid = ahMap.get(nObj.Agency_Hospital__c);
                nObj.Account_Opp__c = hid;
                String rid = deptRectMap.get(nObj.Department_Cateogy__c);

                Account dc = dcMap.get(hid + rid);
                if (dc != null) {
                    nObj.Department_Class_Opp__c = dc.Id;
                    // AccountDailyUpdateBatch のロジックより、OCSM_Owner__c に OwnerId を設定
                    // OCM商談とリンクした時、OCM商談所有者に設定
                    if (String.isBlank(nObj.Change_To_Opportunity__c)) {
                        nObj.OCSM_Owner__c = dc.OwnerId;
                    }
                }

                //OCM商談から作成する時、OCM商談所有者に設定
                if (String.isBlank(nObj.OCSM_Owner__c) && String.isNotBlank(nObj.Change_To_Opportunity__c)) {
                    nObj.OCSM_Owner__c = nObj.OCSM_Opportunity_OwnerId__c;
                }
            }
        }

        List<Opportunity> oppList = [select Id, Agency_Opportunity__c from Opportunity where Id in :opportunitySet];

        for(Opportunity opp : oppList) {
            opp.Agency_Opportunity__c = null;
        }

        update oppList;

    }

    // .询价 Copy 到 询价
    private void afterExecute() {
        Set<Id> opportunitySet = new Set<Id>();
        Map<Id,Id> opportunityMap = new Map<Id,Id>();
        for(Agency_Opportunity__c nObj : newList) {
            if (nObj.Change_To_Opportunity__c != null) {
                opportunitySet.add(nObj.Change_To_Opportunity__c);
                opportunityMap.put(nObj.Change_To_Opportunity__c, nObj.Id);
            }
        }

        List<Opportunity> oppList = [select Id, Agency_Opportunity__c from Opportunity where Id in :opportunitySet];

        for(Opportunity opp : oppList) {
            opp.Agency_Opportunity__c = opportunityMap.get(opp.Id);
        }

        update oppList;
    }

    /**
     * 设定 apex share to role
     * @param accId UserRoleとGroupを取得するため
     */
    private static void setAgency_Contact_Share(Id accId, List<Id> pList) {
        Id grpId = MergeAgencyActivityBatch.accIdGrpIdMap(accId);
        List<Agency_Opportunity__Share> shareList = new List<Agency_Opportunity__Share>();
        Set<Id> sharePIdSet = new Set<Id>();
        for (Agency_Opportunity__Share share : [SELECT Id, ParentId
                FROM Agency_Opportunity__Share
                WHERE UserOrGroupId = :grpId]) {
            sharePIdSet.add(share.ParentId);
        }
        for (Id pId : pList) {
            if (sharePIdSet.contains(pId) == false) {
                Agency_Opportunity__Share apexShare = new Agency_Opportunity__Share(
                        RowCause = 'Manual',
                        ParentId = pId,
                        UserOrGroupId = grpId,
                        AccessLevel = 'Edit');
                shareList.add(apexShare);
            }
        }
        if (System.Test.isRunningTest() && grpId == null) {
            // 没有造 User 的旧Test 也让可以过
            return;
        }
        insert shareList;
    }

    // afterInsert, afterUndelete
    /**
     * 一定要是同一经销商的
     * @param nList {Id, Agency_ID__c}
     */
    public static void shareAgency_Opportunity_ToRole(List<Agency_Opportunity__c> nList) {
        Set<Id> targetAgencyIdSet = new Set<Id>();
        Map<Id, List<Id>> tMap = new Map<Id, List<Id>>();
        for (Agency_Opportunity__c nObj : nList) {
            if (false == String.isBlank(nObj.Agency_ID__c)) {
                targetAgencyIdSet.add(nObj.Agency_ID__c);
                List<Id> tList = tMap.get(nObj.Agency_ID__c);
                if (tList == null) {
                    tList = new List<Id>();
                }
                tList.add(nObj.Id);
                tMap.put(nObj.Agency_ID__c, tList);
            }
        }
        if (targetAgencyIdSet.size() > 0) {
            List<Id> targetIdList = new List<Id> (targetAgencyIdSet);
            System.assertEquals(1, targetIdList.size(), '一定要是同一经销商 [' + targetIdList[0] + ']');
            setAgency_Contact_Share(targetIdList[0], tMap.get(targetIdList[0]));
        }
    }

    // afterInsert, afterUpdate
    // 战略科室的主担当 を取得、Agency_Opportunity__Shareに設定(Read)
    private void shareToOSCM() {
        List<Agency_Opportunity__Share> insertList = new List<Agency_Opportunity__Share>();
        List<Id> deleteTargetAOIdList = new List<Id>();
        String rowCause = Schema.Agency_Opportunity__Share.RowCause.OCSM_Owner_c_User__c;
        //Apex共有の理由名OCSM_Owner_c_User
        for(Agency_Opportunity__c nObj : newList) {
            Agency_Opportunity__c oObj = null;
            if (oldMap != null && oldMap.containsKey(nObj.Id)) {
                oObj = oldMap.get(nObj.Id);
            }
            // 经销商询价报价委托 经销商询价只读改为读写 2020-03-13 update by vivek start
            // if (nObj.Agency_Hospital__c != null && nObj.OCSM_Owner__c != null
            // ) {
            //SWAG-C6U8KE 经销商DAMS系统新增询价报错  精琢技术 thh 2021-09-16 start
            if (nObj.Agency_Hospital__c != null && nObj.OCSM_Owner__c != null && nObj.OCSM_Owner_IsActive__c
            //SWAG-C6U8KE 经销商DAMS系统新增询价报错  精琢技术 thh 2021-09-16 end
                 && (oObj == null
                    || oObj.Department_Class_Opp__c != nObj.Department_Class_Opp__c
                    || oObj.Account_Opp__c          != nObj.Account_Opp__c
                    || oObj.OCSM_Owner__c           != nObj.OCSM_Owner__c
                )
            ) {
                // 经销商询价报价委托 经销商询价只读改为读写 2020-03-13 update by vivek end
                // 经销商询价报价委托 经销商询价只读改为读写 2020-03-13 update by vivek start
                // Agency_Opportunity__Share aos = new Agency_Opportunity__Share(
                //         RowCause = rowCause,
                //         ParentId = nObj.Id,
                //         UserOrGroupId = nObj.OCSM_Owner__c,
                //         AccessLevel = 'Read');
                Agency_Opportunity__Share aos = new Agency_Opportunity__Share(
                        RowCause = rowCause,
                        ParentId = nObj.Id,
                        UserOrGroupId = nObj.OCSM_Owner__c,
                        AccessLevel = 'Edit');
                // 经销商询价报价委托 经销商询价只读改为读写 2020-03-13 update by vivek end   
                insertList.add(aos);
                // SWAG-BJ29Z4 营业助理询价自动审批加入共享 by vivek start
                if(nObj.Sales_Manager__c != null){
                    Agency_Opportunity__Share oppjingli = new Agency_Opportunity__Share(
                        RowCause = rowCause,
                        ParentId = nObj.Id,
                        UserOrGroupId = nObj.Sales_Manager__c,
                        AccessLevel = 'Edit');
                    insertList.add(oppjingli);
                    if (oObj != null && oObj.Sales_Manager__c != nObj.Sales_Manager__c) {
                        deleteTargetAOIdList.add(nObj.Id);
                    }
                }
                // SWAG-BJ29Z4 营业助理询价自动审批加入共享 by vivek end
                if (oObj != null && oObj.OCSM_Owner__c != nObj.OCSM_Owner__c) {
                    deleteTargetAOIdList.add(nObj.Id);
                }
            }
        }

        // 先 Delete 后 Insert
        if (deleteTargetAOIdList.size() > 0) {
            List<Agency_Opportunity__Share> deleteList = [SELECT Id
                FROM Agency_Opportunity__Share
                WHERE RowCause = :rowCause
                  AND ParentId IN :deleteTargetAOIdList
            ];
            delete deleteList;
        }
        insert insertList;
    }
}