public class UserProfileHandler extends Oly_TriggerHandler {

    private Map<Id, User> newMap;
    private Map<Id, User> oldMap;
    private List<User> newList;
    private List<User> oldList;
    @TestVisible private static Set<String> testTargetDepts;

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

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

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

    protected override void afterInsert() {
        dynamicUpdateGroup();
    }

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

    private void InsertAuth() {
        for (User NewUser : newList) {
            // 报价修改权限
            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.OBA2_opportunity)
                    || NewUser.profileid.equals(System.label.OBA7_tender_opp)
                    || NewUser.profileid.equals(System.label.OBA8_NewAcc_Tender_Quote)
                    || NewUser.profileid.equals(System.label.ProfileId_2J3)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Quote_Correct__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2J3)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Quote_Special_Operation__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_0AA_119)
                || NewUser.profileid.equals(System.label.ProfileId_0AA_119_M) // 2022-11-01 Last Buy预留管理改善新需求 拆分经理简档
                || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
                || NewUser.profileid.equals(System.label.ProfileId_2F9_OSH)//20230629 you
                || NewUser.profileid.equals(System.label.OBA4_eSignForm) // 20230726 ssm OBA4增加取消win的权限
                ) {
                NewUser.SAP_Send_OFF__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2_Price)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Sales_proposal__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2_Price)
                    || NewUser.profileid.equals(System.label.ProfileId_2S3)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S5)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2S8)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Service_proposal__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Sales_analysis_proposal__c = true;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2S8)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.CanDownloadHospitalPPT__c = true;
            }
            // SWAG-CAD8VW 20220125 LHJ Start
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileIdN_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.InquiryLostCancel__c = true;
            }
            // SWAG-CAD8VW 20220125 End
        }
    }

    private void UpdateAuth() {
        for (User NewUser : newList) {
            // 报价修改权限
            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.OBA2_opportunity)
                    || NewUser.profileid.equals(System.label.OBA7_tender_opp)
                    || NewUser.profileid.equals(System.label.OBA8_NewAcc_Tender_Quote)
                    || NewUser.profileid.equals(System.label.ProfileId_2J3)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Quote_Correct__c = true;
            } else {
                NewUser.Quote_Correct__c = false;
            }

            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2J3)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Quote_Special_Operation__c = true;
            } else {
                NewUser.Quote_Special_Operation__c = false;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_0AA_119)
                    || NewUser.profileid.equals(System.label.ProfileId_0AA_119_M) // 2022-11-01 Last Buy预留管理改善新需求 拆分经理简档
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
                    || NewUser.profileid.equals(System.label.ProfileId_2F9_OSH)//20230629 you
                    || NewUser.profileid.equals(System.label.OBA4_eSignForm) // 20230726 ssm OBA4增加取消win的权限
               ) {
                NewUser.SAP_Send_OFF__c = true;
            } else {
                NewUser.SAP_Send_OFF__c = false;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2_Price)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Sales_proposal__c = true;
            } else {
                NewUser.Sales_proposal__c = false;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2)
                    || NewUser.profileid.equals(System.label.ProfileId_2S2_Price)
                    || NewUser.profileid.equals(System.label.ProfileId_2S3)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S5)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2S8)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Service_proposal__c = true;
            } else {
                NewUser.Service_proposal__c = false;
            }

            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4)
                    || NewUser.profileid.equals(System.label.ProfileId_2S4_Chief)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.Sales_analysis_proposal__c = true;
            } else {
                NewUser.Sales_analysis_proposal__c = false;
            }
            if (NewUser.profileid.equals(System.label.ProfileId_2S6)
                    || NewUser.profileid.equals(System.label.ProfileId_2S6_ENG)
                    || NewUser.profileid.equals(System.label.ProfileId_2S8)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.CanDownloadHospitalPPT__c = true;
            } else {
                NewUser.CanDownloadHospitalPPT__c = false;
            }
            // SWAG-CAD8VW 20220125 LHJ Start
            if (NewUser.profileid.equals(System.label.ProfileId_2S1)
                    || NewUser.profileid.equals(System.label.ProfileIdN_2S1)
                    || NewUser.profileid.equals(System.label.ProfileId_2M4)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdmin)
                    || NewUser.profileid.equals(System.label.ProfileId_SystemAdminGPI)
               ) {
                NewUser.InquiryLostCancel__c = true;
            } else {
                NewUser.InquiryLostCancel__c = false;
            }
            // SWAG-CAD8VW 20220125 LHJ End
        }
    }

    /**
     * 动态更新 Group (备品共享_杭州_华东营业本部)
     * Condition:
     *    - after insert
     *    - after update, CSM管理省(备品用)（OCM_man_province_Rental__c）+本部（选项）（Dept__c）
     *    - Dept__c IN ('医疗华北营业本部','医疗东北营业本部','医疗西北营业本部','医疗华东营业本部','医疗华南营业本部','医疗西南营业本部')
     * Execute:
     *    - 找 Group, 然后 把 人 加进去
     *    - 没有 Group的时候, 新建 Group
     *    - Group 对应的 ShareRule (共享到) 没有的话 报错 (邮件通知 维护 ShareRule)
     */
    private void dynamicUpdateGroup() {
        Set<String> targetDepts = new Set<String> {'医疗华北营业本部','医疗东北营业本部','医疗西北营业本部','医疗华东营业本部','医疗华南营业本部','医疗西南营业本部'};
        if (System.Test.isRunningTest() && testTargetDepts != null) {
            targetDepts = testTargetDepts;
        }
        Set<String> targetProvs = new Set<String>(AssetWebService.getOcmMgtProvMap().values());
        //String USER_PREFIX_005 = Schema.SObjectType.User.getKeyPrefix();

        // 操作对象 Group
        Set<String> delTargetGroupsName = new Set<String>();
        Set<String> insTargetGroupsName = new Set<String>();
        // Delete对象User
        List<Id> deleteTargetUsers = new List<Id>();
        // 加到 GroupMember 的对象User
        List<User> insertTargetUsers = new List<User>();

        // 找 Group
        // Validation Check 用
        for (User nObj : newList) {
            User oObj = (null == this.oldMap) ? null : this.oldMap.get(nObj.Id);

            // 作成, 确认字段有没有变化
            if (Trigger.isInsert
                || (oObj != null
                    && ((oObj.IsActive != nObj.IsActive && nObj.IsActive)
                        || oObj.Work_Location__c != nObj.Work_Location__c
                        || oObj.Dept__c != nObj.Dept__c
                    )
                )
            ) {
                // 动态更新対象 --> Validation対象
                if (targetDepts.contains(nObj.Dept__c)
                    && (targetProvs.contains(nObj.OCM_man_province_Rental__c)
                       || (testTargetDepts != null && testTargetDepts.contains(nObj.Dept__c))    // isRunningTest 用
                    )
                ) {
                    if(String.isNotBlank(nObj.Dept__c)) {
                        String targetGroupName = '备品共享_'
                                + nObj.OCM_man_province_Rental__c + '_' + nObj.Dept__c.replace('医疗', '');
                        insTargetGroupsName.add(targetGroupName);
                    }
                }
            }
        }

        Map<String, Id> findGroupNameMap = new Map<String, Id>();
        for (Group grp : [SELECT Id, Name FROM Group WHERE Type = 'Regular' AND Name IN: insTargetGroupsName]) {
            findGroupNameMap.put(grp.Name, grp.Id);
        }

        // 动态更新 Group (备品共享_XXXX)
        Set<Id> addErrorUserIds = new Set<Id>();
        for (User nObj : newList) {
            User oObj = (null == this.oldMap) ? null : this.oldMap.get(nObj.Id);
            // 作成, 确认字段有没有变化
            if (Trigger.isInsert
                || (oObj != null
                    && ((oObj.IsActive != nObj.IsActive && nObj.IsActive)
                        || oObj.Work_Location__c != nObj.Work_Location__c
                        || oObj.Dept__c != nObj.Dept__c
                    )
                )
            ) {
                // 动态更新対象
                if (targetDepts.contains(nObj.Dept__c)
                    && (targetProvs.contains(nObj.OCM_man_province_Rental__c)
                       || nObj.OCM_man_province_Rental__c == nObj.Dept__c
                       || (testTargetDepts != null && testTargetDepts.contains(nObj.Dept__c))    // isRunningTest 用
                    )
                ) {
                    insertTargetUsers.add(nObj);
                }

                // 删除对象
                if (oObj != null
                    && addErrorUserIds.contains(oObj.Id) == false
                    && (targetDepts.contains(oObj.Dept__c)
                        || targetDepts.contains(nObj.Dept__c))
                ) {
                    if(String.isNotBlank(oObj.Dept__c)) {
                        String targetGroupName = '备品共享_'
                                + oObj.OCM_man_province_Rental__c + '_' + oObj.Dept__c.replace('医疗', '');
                        delTargetGroupsName.add(targetGroupName);
                        deleteTargetUsers.add(oObj.Id);
                    }
                }
            }
        }

        // 先Delete
        List<GroupMember> deleteGM = [SELECT Id, UserOrGroupId
                 FROM GroupMember
                WHERE Group.Type = 'Regular'
                  AND Group.Name IN: delTargetGroupsName
                  AND UserOrGroupId IN: deleteTargetUsers];
        if (deleteGM.size() > 0) { delete deleteGM; }

        // 再Insert
        // 找到 Group的时候, 直接 Insert Group Member
        List<GroupMember> insertGM = new List<GroupMember>();
        Map<String, String> newGrpUsers = new Map<String, String>();
        for (User nObj : insertTargetUsers) {
            String grpName = '备品共享_' + nObj.OCM_man_province_Rental__c + '_' + nObj.Dept__c.replace('医疗', '');
            if (findGroupNameMap.containsKey(grpName)) {
                insertGM.add(new GroupMember(
                    GroupId = findGroupNameMap.get(grpName),
                    UserOrGroupId = nObj.Id
                ));
            } else {
                if (newGrpUsers.containsKey(grpName)) {
                    newGrpUsers.put(grpName, newGrpUsers.get(grpName) + ', ' + nObj.Id);
                } else {
                    newGrpUsers.put(grpName, nObj.Id);
                }
            }
        }
        if (insertGM.size() > 0) { insert insertGM; }

        // 没有 Group的时候, 新建 Group, @future Insert Group Member
        if (newGrpUsers.size() > 0) {
            // 新建 Group
            List<Group> insertGroup = new List<Group>();
            for (String grpName : newGrpUsers.keySet()) {
                insertGroup.add(new Group(
                    Name = grpName
                ));
            }
            insert insertGroup;

            Map<String, String> grpIdNewUsers = new Map<String, String>();
            for (Group grp : insertGroup) {
                grpIdNewUsers.put(grp.Id, newGrpUsers.get(grp.Name));
            }
            if (grpIdNewUsers.size() > 0) { UserProfileHandler.futureInsertGroupMember(JSON.serialize(grpIdNewUsers)); }
        }
    }

    @future
    /**
     * 新建 Group, Insert Group Member
     * @param grpIdNewUsersJson Json String of Map<String, String>, {"G1_Id": "U1_Id, U2_Id, ..."}
     */
    @TestVisible
    private static void futureInsertGroupMember(String grpIdNewUsersJson) {
        Map<String, Object> grpIdNewUsers = (Map<String, Object>) JSON.deserializeUntyped(grpIdNewUsersJson);
        if (grpIdNewUsers.isEmpty()) { return; }

        // Insert Group Member
        List<GroupMember> insertGM = new List<GroupMember>();
        for (String grpId : grpIdNewUsers.keySet()) {
            for (String userId : ((String) grpIdNewUsers.get(grpId)).split(',')) {
                insertGM.add(new GroupMember(
                    GroupId = grpId,
                    UserOrGroupId = userId.trim()
                ));
            }
        }
        if (insertGM.size() > 0) { insert insertGM; }
    }
}