package datasync.service;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import datasync.common.ResultJavaEntity;
import datasync.model.OuInfoJavaModel;
import datasync.model.PositionJavaModel;
import datasync.model.UserInfoJavaModel;

/**
 * 抽象同步Service类, 提供有一些共通的同步用方法。此类只作简单同步继承使用, 复杂逻辑同步可自行实现不需要继承该类
 */
public abstract class AbstractSyncJavaService {
    // 自定义map的key
    public static final String MAPKEY_USER_SYNC_ADD = "userSyncAdd";
    public static final String MAPKEY_USER_SYNC_UPDATE = "userSyncUpdate";
    public static final String MAPKEY_USER_SYNC_DISABLE = "userSyncDisable";
    public static final String MAPKEY_ORG_SYNC_ADD = "orgSyncAdd";
    public static final String MAPKEY_ORG_SYNC_UPDATE = "orgSyncUpdate";
    public static final String MAPKEY_ORG_SYNC_DELETE = "orgSyncDelete";
    public static final String MAPKEY_POS_SYNC_ADD = "posSyncAdd";
    public static final String MAPKEY_POS_SYNC_UPDATE = "posSyncUpdate";
    // 请求同步接口成功返回码
    public static final String SYNC_CODE_SUCCESS = "0";
    public static final int SYNC_RESULT_SUCCESS = 1;
    public static final String SET_MANAGERNO_SUCCESS = "1";
    // 岗位类别的默认值
    public static final String POSITION_CLASS_DEFAULT = "未分类";
    public static final String POSITION_CLASS_SEPARATOR = ";";
    // 日期格式化用
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat YYMMDD_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
    // 记录日志
    public static Logger LOGGER = LogManager.getLogger(AbstractSyncJavaService.class);

    // 请求同步接口的service
    protected SyncPositionJavaService positionService = new SyncPositionJavaService();
    protected SyncOrgJavaService orgService = new SyncOrgJavaService();
    protected SyncUserJavaService userService = new SyncUserJavaService();
    // 用于存放数据库查询到的数据的集合
    private List<PositionJavaModel> positionListFromDB = new ArrayList<PositionJavaModel>(0);
    private List<OuInfoJavaModel> ouInfoListFromDB = new ArrayList<OuInfoJavaModel>(0);
    private List<UserInfoJavaModel> userInfoListFromDB = new ArrayList<UserInfoJavaModel>(0);

    // 参数配置
    private String apikey;
    private String secretkey;
    private String baseUrl;
    // 全量增量区分
    private String modeFull = "1";// 默认为1
    private String modeUpdate = "2";// 默认为2
    // 是否提供岗位id标志（客户提供的岗位数据中没有岗位id或者提供了包含岗位id的岗位数据但人员数据中关联的只有岗位名时需设置该值为false）
    private boolean isPosIdProvided = true;// 默认为已提供
    // 子类同步service的类名
    private String syncServiceName;

    public void setApikey(String apikey) {
        this.apikey = apikey;
    }

    public void setSecretkey(String secretkey) {
        this.secretkey = secretkey;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    /**
     * 设置全量模式定义的值, 若未自定义无需设置。默认值为"1"
     *
     * @param modeFull
     */
    public void setModeFull(String modeFull) {
        this.modeFull = modeFull;
    }

    /**
     * 设置增量模式定义的值, 若未自定义无需设置。默认值为"2"
     *
     * @param modeUpdate
     */
    public void setModeUpdate(String modeUpdate) {
        this.modeUpdate = modeUpdate;
    }

    /**
     * 客户提供的岗位数据中没有岗位id或者提供了包含岗位id的岗位数据但人员数据中关联的只有岗位名时需设置该值为false。默认为已提供
     *
     * @param isPosIdProvided
     */
    public void setIsPosIdProvided(boolean isPosIdProvided) {
        this.isPosIdProvided = isPosIdProvided;
    }

    /**
     * 设置子类同步service的类名，记录日志时用
     *
     * @param syncServiceName
     */
    public void setSyncServiceName(String syncServiceName) {
        this.syncServiceName = syncServiceName;
    }

    /**
     * 对外提供的同步程序的启动方法
     */
    public void execute() {
        try {
            sync();
        } catch (Exception e) {
            LOGGER.error("定时同步[" + syncServiceName + "]出现异常", e);
            try {
                Thread.sleep(10 * 1000);
                sync();
            } catch (Exception ex) {
                LOGGER.error("定时同步[" + syncServiceName + "]出现异常", ex);
            }
        }
    }

    /**
     * 同步主方法。注意同步顺序：部门>岗位>人员
     *
     * @throws Exception
     */
    public void sync() throws Exception {
        LOGGER.info("定时同步[" + syncServiceName + "]开始");
        ouInfoListFromDB = getOuInfoListFromDB();
        int orgCount = ouInfoListFromDB.size();
        if (orgCount > 0) {
            // 组织增量同步
            opOrgSync(modeUpdate, 0);
        } else {
            // 组织全量同步
            opOrgSync(modeFull, 0);
        }

        positionListFromDB = getPositionsFromDB();
        int posCount = positionListFromDB.size();
        if (posCount > 0) {
            // 岗位增量同步
            opPosSync(modeUpdate);
        } else {
            // 岗位全量同步
            opPosSync(modeFull);
        }

        userInfoListFromDB = getUserInfoListFromDB();
        int userCount = userInfoListFromDB.size();
        // 用户表数据默认有3条员工数据
        if (userCount > 3) {
            // 用户增量同步
            opUserSync(modeUpdate, 1);
        } else {
            // 用户全量同步
            opUserSync(modeFull, 1);
        }
        LOGGER.info("定时同步[" + syncServiceName + "]结束");

        // 释放内存
        ouInfoListFromDB = null;
        positionListFromDB = null;
        userInfoListFromDB = null;
    }

    /**
     * 岗位同步
     *
     * @param mode 全量增量区分
     * @throws Exception
     */
    public void opPosSync(String mode) throws Exception {
        List<PositionJavaModel> newList = getPositionModelList(mode);
        LOGGER.info("岗位同步[" + syncServiceName + "]Total Size: " + newList.size());

        removeExpiredPos(newList);

        // 全量模式
        if (modeFull.equals(mode)) {
            LOGGER.info("岗位同步[" + syncServiceName + "]新增Size: " + newList.size());
            setFullPosNames(newList);
            syncAddPosOneByOne(newList);
        }
        // 增量模式
        else {
            Map<String, List<PositionJavaModel>> map = null;
            if (isPosIdProvided) {
                map = comparePosList1(positionListFromDB, newList);
            } else {
                map = comparePosList2(positionListFromDB, newList);
            }

            List<PositionJavaModel> posToSyncAdd = map.get(MAPKEY_POS_SYNC_ADD);
            if (posToSyncAdd != null && posToSyncAdd.size() > 0) {
                setFullPosNames(posToSyncAdd);
                syncAddPosOneByOne(posToSyncAdd);
            }

            List<PositionJavaModel> posToSyncUpdate = map.get(MAPKEY_POS_SYNC_UPDATE);
            if (posToSyncUpdate != null && posToSyncUpdate.size() > 0) {
                syncUpdatePosOneByOne(posToSyncUpdate);
            }
        }
    }

    /**
     * 组织同步
     *
     * @param mode       全量增量区分
     * @param isBaseInfo 同步接口需传字段
     * @throws Exception
     */
    public void opOrgSync(String mode, int isBaseInfo) throws Exception {
        List<OuInfoJavaModel> newList = getOuInfoModelList(mode);
        LOGGER.info("组织同步[" + syncServiceName + "]Total Size: " + newList.size());

        // 此处将需要删除的组织从集合中去除 提升同步新增效率
        List<OuInfoJavaModel> expiredOrgs = removeExpiredOrgs(newList, mode);
        setRootOrgParentId(newList);

        // 全量模式
        if (modeFull.equals(mode)) {
            // 此处再次同步删除过期组织
            if (expiredOrgs.size() > 0) {
                LOGGER.info("组织同步[" + syncServiceName + "]删除Size: " + expiredOrgs.size());
                syncDeleteOrgOneByOne(expiredOrgs, false);
            }

            LOGGER.info("组织同步[" + syncServiceName + "]新增Size: " + newList.size());
            // 进行多次同步
            for (int i = 0; i < 3; i++) {
                syncAddOrUpdateOrgOneByOne(newList, isBaseInfo);
            }
        }
        // 增量模式
        else {
            Map<String, List<OuInfoJavaModel>> map = compareOrgList(ouInfoListFromDB, newList);

            List<OuInfoJavaModel> orgsToSyncDelete = map.get(MAPKEY_ORG_SYNC_DELETE);
            if (orgsToSyncDelete != null && orgsToSyncDelete.size() > 0) {
                syncDeleteOrgOneByOne(orgsToSyncDelete, true);
            }

            List<OuInfoJavaModel> orgsToSyncAdd = map.get(MAPKEY_ORG_SYNC_ADD);
            if (orgsToSyncAdd != null && orgsToSyncAdd.size() > 0) {
                syncAddOrUpdateOrgOneByOne(orgsToSyncAdd, isBaseInfo);
            }

            List<OuInfoJavaModel> orgsToSyncUpdate = map.get(MAPKEY_ORG_SYNC_UPDATE);
            if (orgsToSyncUpdate != null && orgsToSyncUpdate.size() > 0) {
                syncAddOrUpdateOrgOneByOne(orgsToSyncUpdate, isBaseInfo);
            }
        }
    }

    /**
     * 用户同步
     *
     * @param mode   全量增量区分
     * @param islink 是否同步用户基本信息
     * @throws Exception
     */
    public void opUserSync(String mode, int islink) throws Exception {
        List<UserInfoJavaModel> newList = getUserInfoModelList(mode);
        LOGGER.info("用户同步[" + syncServiceName + "]Total Size: " + newList.size());

        changePropValues(newList);
        // 此处将需要删除的用户从集合中去除 提升同步新增效率
        List<UserInfoJavaModel> expiredUsers = removeExpiredUsers(newList, mode);
        if (!isPosIdProvided) {
            setPositionNoToUser(newList);
        }

        // 全量模式
        if (modeFull.equals(mode)) {
            // 同步禁用过期用户
            if (expiredUsers.size() > 0) {
                LOGGER.info("用户同步[" + syncServiceName + "]禁用Size: " + expiredUsers.size());
                syncDisableUserOneByOne(expiredUsers, false);
            }

            LOGGER.info("用户同步[" + syncServiceName + "]新增Size: " + newList.size());
            syncAddUserOneByOne(newList, islink);
        }
        // 增量模式
        else {
            // 与增量list进行比较
            Map<String, List<UserInfoJavaModel>> map = compareUserList(userInfoListFromDB, newList);

            List<UserInfoJavaModel> usersToDisable = map.get(MAPKEY_USER_SYNC_DISABLE);
            if (usersToDisable != null && usersToDisable.size() > 0) {
                syncDisableUserOneByOne(usersToDisable, true);
            }

            List<UserInfoJavaModel> usersToSyncAdd = map.get(MAPKEY_USER_SYNC_ADD);
            if (usersToSyncAdd != null && usersToSyncAdd.size() > 0) {
                syncAddUserOneByOne(usersToSyncAdd, islink);
            }

            List<UserInfoJavaModel> usersToSyncUpdate = map.get(MAPKEY_USER_SYNC_UPDATE);
            if (usersToSyncUpdate != null && usersToSyncUpdate.size() > 0) {
                syncUpdateUserOneByOne(usersToSyncUpdate, islink);
            }
        }

    }

    /**
     * 岗位全量数据集合与最新获取岗位数据集合进行比较(已提供岗位编号)
     *
     * @param fullList 全量岗位数据集合
     * @param newList  最新获取岗位数据集合
     * @return 包含 同步新增和更新的岗位集合的Map对象
     */
    protected Map<String, List<PositionJavaModel>> comparePosList1(List<PositionJavaModel> fullList,
                                                                   List<PositionJavaModel> newList) {
        Map<String, List<PositionJavaModel>> map = new HashMap<String, List<PositionJavaModel>>();
        List<PositionJavaModel> posToSyncAdd = new ArrayList<PositionJavaModel>();
        List<PositionJavaModel> posToSyncUpdate = new ArrayList<PositionJavaModel>();

        for (PositionJavaModel newPos : newList) {
            // 岗位不存在新增
            if (!fullList.contains(newPos)) {
                posToSyncAdd.add(newPos);
            } else {
                String newPosNo = newPos.getpNo();
                if (newPosNo != null) {
                    for (PositionJavaModel fullPos : fullList) {
                        // 根据岗位编号进行比较
                        if (newPosNo.equals(fullPos.getpNo())) {
                            String newPosName = newPos.getpNames();
                            // 岗位名发生更新
                            if (newPosName != null && !newPosName.equals(fullPos.getpNames())) {
                                posToSyncUpdate.add(newPos);
                            }
                            break;
                        }
                    }
                }
            }
        }

        map.put(MAPKEY_POS_SYNC_ADD, posToSyncAdd);
        map.put(MAPKEY_POS_SYNC_UPDATE, posToSyncUpdate);
        LOGGER.info("岗位同步[" + syncServiceName + "]新增Size: " + posToSyncAdd.size());
        LOGGER.info("岗位同步[" + syncServiceName + "]更新Size: " + posToSyncUpdate.size());

        return map;
    }

    /**
     * 岗位全量数据集合与最新获取岗位数据集合进行比较(未提供岗位编号)
     *
     * @param fullList 全量岗位数据集合
     * @param newList  最新获取岗位数据集合
     * @return 包含 同步新增的岗位集合的Map对象
     */
    protected Map<String, List<PositionJavaModel>> comparePosList2(List<PositionJavaModel> fullList,
                                                                   List<PositionJavaModel> newList) {
        Map<String, List<PositionJavaModel>> map = new HashMap<String, List<PositionJavaModel>>();
        List<PositionJavaModel> posToSyncAdd = new ArrayList<PositionJavaModel>();

        // 待新增岗位
        for (PositionJavaModel newPos : newList) {
            String newPosName = newPos.getpNames();

            if (newPosName != null) {
                boolean isPosNameExist = false;

                for (PositionJavaModel fullPos : fullList) {
                    // 根据岗位名进行比较
                    if (newPosName.equals(fullPos.getpNames())) {
                        isPosNameExist = true;
                        break;
                    }
                }

                // 岗位名不存在
                if (!isPosNameExist) {
                    posToSyncAdd.add(newPos);
                }
            }
        }

        map.put(MAPKEY_POS_SYNC_ADD, posToSyncAdd);
        LOGGER.info("岗位同步[" + syncServiceName + "]新增Size: " + posToSyncAdd.size());

        return map;
    }

    /**
     * 组织全量数据集合与最新获取组织数据集合进行比较
     *
     * @param fullList 全量组织数据集合
     * @param newList  最新获取组织数据集合
     * @return 包含 同步新增、更新、 删除等组织集合的Map对象
     */
    protected Map<String, List<OuInfoJavaModel>> compareOrgList(List<OuInfoJavaModel> fullList, List<OuInfoJavaModel> newList) {
        Map<String, List<OuInfoJavaModel>> map = new HashMap<String, List<OuInfoJavaModel>>();

        List<OuInfoJavaModel> orgsToSyncAdd = new ArrayList<OuInfoJavaModel>();
        List<OuInfoJavaModel> orgsToSyncUpdate = new ArrayList<OuInfoJavaModel>();
        List<OuInfoJavaModel> orgsToSyncDelete = new ArrayList<OuInfoJavaModel>();

        for (OuInfoJavaModel newOrg : newList) {
            // 待新增组织
            if (!fullList.contains(newOrg)) {
                // 非过期组织
                if (!isOrgExpired(newOrg)) {
                    orgsToSyncAdd.add(newOrg);
                } else {
                    // logger.info("包含过期组织：" + newOrg.getOuName());
                }
            }
            // 已经存在的组织比较
            else {
                // 组织过期待删除
                if (isOrgExpired(newOrg)) {
                    orgsToSyncDelete.add(newOrg);
                } else {
                    // 组织更新
                    orgsToSyncUpdate.add(newOrg);
                }
            }
        }

        map.put(MAPKEY_ORG_SYNC_ADD, orgsToSyncAdd);
        map.put(MAPKEY_ORG_SYNC_UPDATE, orgsToSyncUpdate);
        map.put(MAPKEY_ORG_SYNC_DELETE, orgsToSyncDelete);

        LOGGER.info("组织同步[" + syncServiceName + "]新增Size: " + orgsToSyncAdd.size());
        LOGGER.info("组织同步[" + syncServiceName + "]更新Size: " + orgsToSyncUpdate.size());
        LOGGER.info("组织同步[" + syncServiceName + "]删除Size: " + orgsToSyncDelete.size());

        return map;
    }

    /**
     * 用户全量数据集合与最新获取用户数据集合进行比较
     *
     * @param fullList 全量用户数据集合
     * @param newList  最新获取用户数据集合
     * @return 包含 同步新增、更新、禁用等用户集合的Map对象
     */
    protected Map<String, List<UserInfoJavaModel>> compareUserList(List<UserInfoJavaModel> fullList,
                                                                   List<UserInfoJavaModel> newList) {
        Map<String, List<UserInfoJavaModel>> map = new HashMap<String, List<UserInfoJavaModel>>();

        List<UserInfoJavaModel> usersToSyncAdd = new ArrayList<UserInfoJavaModel>();
        List<UserInfoJavaModel> usersToSyncUpdate = new ArrayList<UserInfoJavaModel>();
        List<UserInfoJavaModel> usersToSyncDisable = new ArrayList<UserInfoJavaModel>();

        for (UserInfoJavaModel newUser : newList) {
            // 待新增用户
            if (!fullList.contains(newUser)) {
                if (!isUserExpired(newUser)) {
                    usersToSyncAdd.add(newUser);
                } else {
                    // logger.info("包含过期员工：" + newUser.getId());
                }
            }
            // 已经存在的用户比较
            else {
                if (isUserExpired(newUser)) {
                    // 用户过期禁用
                    usersToSyncDisable.add(newUser);
                } else {
                    // 存在用户更新
                    usersToSyncUpdate.add(newUser);
                }
            }
        }

        map.put(MAPKEY_USER_SYNC_ADD, usersToSyncAdd);
        map.put(MAPKEY_USER_SYNC_UPDATE, usersToSyncUpdate);
        map.put(MAPKEY_USER_SYNC_DISABLE, usersToSyncDisable);

        LOGGER.info("用户同步[" + syncServiceName + "]新增Size: " + usersToSyncAdd.size());
        LOGGER.info("用户同步[" + syncServiceName + "]更新Size: " + usersToSyncUpdate.size());
        LOGGER.info("用户同步[" + syncServiceName + "]禁用Size: " + usersToSyncDisable.size());

        return map;
    }

    /**
     * 根据用户数据集合生成岗位对象集合（客户未提供岗位数据仅提供包含了岗位名的人员数据时调用该方法）
     *
     * @param userModelList
     * @return 岗位对象集合
     */
    protected List<PositionJavaModel> getPosListFromUsers(List<UserInfoJavaModel> userModelList) {
        // 使用Set保证无重复
        Set<String> posNames = new HashSet<String>();
        for (UserInfoJavaModel modle : userModelList) {
            // 只取非过期账号的岗位
            if (!isUserExpired(modle)) {
                posNames.add(modle.getPostionName());
            }
        }

        List<PositionJavaModel> list = new ArrayList<PositionJavaModel>(posNames.size());
        PositionJavaModel temp = null;
        for (String posName : posNames) {
            temp = new PositionJavaModel();
            // 随机生成岗位编号
            temp.setpNo(UUID.randomUUID().toString());
            temp.setpNames(posName);
            list.add(temp);
        }

        return list;
    }

    /**
     * 关联岗位编号到用户（人员数据中只有岗位名没有岗位id数据）
     *
     * @param newList
     * @throws Exception
     */
    protected void setPositionNoToUser(List<UserInfoJavaModel> newList) throws Exception {
        // 首次同步positionListFromDB为空的情况
        if (positionListFromDB.size() == 0) {
            // 重新从数据库获取岗位数据
            positionListFromDB = getPositionsFromDB();
        }

        for (UserInfoJavaModel user : newList) {
            String pNameInUser = user.getPostionName();

            if (pNameInUser != null) {
                for (PositionJavaModel pos : positionListFromDB) {
                    // 根据岗位名(不带岗位类别)进行查找
                    if (pNameInUser.equals(pos.getpNames())) {
                        user.setPostionNo(pos.getpNo());
                        break;
                    }
                }
            }
        }
    }

    /**
     * 关联数据库岗位编号到用户（人员数据中只有岗位名没有岗位id数据），供自行实现同步时调用
     *
     * @param newList
     * @throws Exception
     */
    protected void setDBPositionNoToUser(List<UserInfoJavaModel> newList) throws Exception {
        // 获取数据库岗位数据
        List<PositionJavaModel> positionListDB = getPositionsFromDB();

        for (UserInfoJavaModel user : newList) {
            String pNameInUser = user.getPostionName();

            if (pNameInUser != null) {
                for (PositionJavaModel pos : positionListDB) {
                    // 根据岗位名(不带岗位类别)进行查找
                    if (pNameInUser.equals(pos.getpNames())) {
                        user.setPostionNo(pos.getpNo());
                        break;
                    }
                }
            }
        }

        positionListDB = null;
    }

    /**
     * 设置岗位名为带类别岗位名(同步新增岗位之前设置)
     *
     * @param newList
     */
    protected void setFullPosNames(List<PositionJavaModel> newList) {
        String prefix = POSITION_CLASS_DEFAULT + POSITION_CLASS_SEPARATOR;
        for (PositionJavaModel pos : newList) {
            // 岗位类别名
            String pNameClass = pos.getpNameClass();
            if (StringUtils.isBlank(pNameClass)) {
                pos.setpNames(prefix + pos.getpNames());
            } else {
                pos.setpNames(pNameClass + POSITION_CLASS_SEPARATOR + pos.getpNames());
            }
        }
    }

    /**
     * 从pNames中得到岗位名(pNames格式: 一级类别;二级类别;岗位名)
     *
     * @param pNames
     * @return 不带类别的岗位名
     */
    protected String getPositionName(String pNames) {
        if (pNames == null) {
            return null;
        }

        String[] arr = pNames.split(POSITION_CLASS_SEPARATOR);
        int len = arr.length;
        if (len == 0) {
            return null;
        }

        // 最后是岗位名
        return arr[len - 1];
    }

    /**
     * 不同组织存在同岗位名时调用该方法获取组织名作为岗位类别名(前提：1人员中关联的是岗位id，2同岗位名对应多个岗位id，3岗位数据中有所属组织id)
     *
     * @param orgId
     * @return 作为岗位类别的组织名
     * @throws Exception
     */
    protected String getPositionNameClassFromOrgs(String orgId) throws Exception {
        // 首次同步ouInfoListFromDB为空的情况
        if (ouInfoListFromDB.size() == 0) {
            // 重新从数据库获取部门数据
            ouInfoListFromDB = getOuInfoListFromDB();
        }
        String pNameClass = null;
        if (orgId != null) {
            for (OuInfoJavaModel org : ouInfoListFromDB) {
                if (orgId.equals(org.getId())) {
                    pNameClass = org.getOuName();
                    break;
                }
            }
        }
        return pNameClass;
    }

    /**
     * 去除过期岗位
     *
     * @param list
     */
    protected void removeExpiredPos(List<PositionJavaModel> list) {
        for (Iterator<PositionJavaModel> iterator = list.iterator(); iterator.hasNext(); ) {
            PositionJavaModel pos = iterator.next();
            if (isPosExpired(pos)) {
                iterator.remove();
                // logger.info("删除了过期岗位：" + pos.getpNames());
            }
        }
    }

    /**
     * 去除过期组织
     *
     * @param list
     * @param mode
     * @return 过期组织集合
     */
    protected List<OuInfoJavaModel> removeExpiredOrgs(List<OuInfoJavaModel> list, String mode) {
        List<OuInfoJavaModel> expiredOrgs = new ArrayList<OuInfoJavaModel>();
        // 仅全量模式下执行
        if (modeFull.equals(mode)) {
            for (Iterator<OuInfoJavaModel> iterator = list.iterator(); iterator.hasNext(); ) {
                OuInfoJavaModel org = iterator.next();
                if (isOrgExpired(org)) {
                    expiredOrgs.add(org);
                    iterator.remove();
                    // logger.info("删除了过期组织：" + org.getOuName());
                }
            }

        }
        return expiredOrgs;
    }

    /**
     * 删除过期员工
     *
     * @param list
     * @param mode
     * @return 过期员工集合
     */
    protected List<UserInfoJavaModel> removeExpiredUsers(List<UserInfoJavaModel> list, String mode) {
        List<UserInfoJavaModel> expiredUsers = new ArrayList<UserInfoJavaModel>();
        // 仅全量模式下执行
        if (modeFull.equals(mode)) {
            for (Iterator<UserInfoJavaModel> iterator = list.iterator(); iterator.hasNext(); ) {
                UserInfoJavaModel user = iterator.next();
                if (isUserExpired(user)) {
                    expiredUsers.add(user);
                    iterator.remove();
                }
            }
        }
        return expiredUsers;
    }

    /**
     * 逐个岗位同步新增
     *
     * @param posToSync
     */
    protected void syncAddPosOneByOne(List<PositionJavaModel> posToSync) {
        List<PositionJavaModel> tempList = new ArrayList<PositionJavaModel>();
        ResultJavaEntity resultJavaEntity = null;
        for (PositionJavaModel pos : posToSync) {
            tempList.add(pos);

            try {
                resultJavaEntity = positionService.position(tempList, apikey, secretkey, baseUrl);

                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    printLog("岗位同步[" + syncServiceName + "]新增失败 ", pos.getpNames(), resultJavaEntity);
                }
            } catch (IOException e) {
                LOGGER.error("岗位同步[" + syncServiceName + "]新增失败 " + pos.getpNames(), e);
            }

            tempList.clear();
        }
    }

    /**
     * 逐个岗位同步更新
     *
     * @param posToSync
     */
    protected void syncUpdatePosOneByOne(List<PositionJavaModel> posToSync) {
        ResultJavaEntity resultJavaEntity = null;
        for (PositionJavaModel pos : posToSync) {
            try {
                // 更新岗位名不带分级类别
                resultJavaEntity = positionService.updatePositionInfo(pos.getpNo(), getPositionName(pos.getpNames()), apikey,
                        secretkey, baseUrl);

                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    printLog("岗位同步[" + syncServiceName + "]更新失败 ", pos.getpNo(), resultJavaEntity);
                }
            } catch (IOException e) {
                LOGGER.error("岗位同步[" + syncServiceName + "]更新失败 " + pos.getpNames(), e);
            }

        }
    }

    /**
     * 逐个组织同步新增或更新
     *
     * @param orgsToSyncAddOrUpdate
     * @param isBaseInfo
     */
    protected void syncAddOrUpdateOrgOneByOne(List<OuInfoJavaModel> orgsToSyncAddOrUpdate, int isBaseInfo) {
        List<OuInfoJavaModel> tempList = new ArrayList<OuInfoJavaModel>();
        ResultJavaEntity resultJavaEntity = null;
        for (OuInfoJavaModel org : orgsToSyncAddOrUpdate) {
            tempList.add(org);

            try {
                resultJavaEntity = orgService.ous(isBaseInfo, tempList, apikey, secretkey, baseUrl);
                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    // 设置部门主管
                    String managerId = org.getManagerNo();
                    if (StringUtils.isNotBlank(managerId)) {
                        resultJavaEntity = orgService.setmanager(managerId, org.getId(), 0, apikey, secretkey, baseUrl);
                        if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                            printLog("设置部门主管[" + syncServiceName + "]失败 ", org.getOuName() + managerId, resultJavaEntity);
                        }
                    }
                } else {
                    printLog("组织同步[" + syncServiceName + "]失败 ", org.getOuName(), resultJavaEntity);
                }
            } catch (IOException e) {
                LOGGER.error("组织同步[" + syncServiceName + "]失败 " + org.getOuName(), e);
            }

            tempList.clear();
        }
    }

    /**
     * 逐个组织同步删除
     *
     * @param orgsToSyncDelete
     * @param ifPringLog
     */
    protected void syncDeleteOrgOneByOne(List<OuInfoJavaModel> orgsToSyncDelete, boolean ifPringLog) {
        List<String> tempList = new ArrayList<String>();
        ResultJavaEntity resultJavaEntity = null;
        for (OuInfoJavaModel org : orgsToSyncDelete) {
            tempList.add(org.getId());

            try {
                resultJavaEntity = orgService.deleteous(tempList, apikey, secretkey, baseUrl);

                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    if (ifPringLog) {
                        printLog("组织同步[" + syncServiceName + "]删除失败 ", org.getOuName(), resultJavaEntity);
                    }
                }
            } catch (IOException e) {
                LOGGER.error("组织同步[" + syncServiceName + "]删除失败 " + org.getOuName(), e);
            }

            tempList.clear();
        }

    }

    /**
     * 逐个用户同步新增
     *
     * @param usersToSyncAdd
     * @param islink
     */
    protected void syncAddUserOneByOne(List<UserInfoJavaModel> usersToSyncAdd, int islink) {
        syncUpdateUserOneByOne(usersToSyncAdd, islink);
    }

    /**
     * 逐个用户同步更新
     *
     * @param usersToSyncUpdate
     * @param islink
     */
    protected void syncUpdateUserOneByOne(List<UserInfoJavaModel> usersToSyncUpdate, int islink) {
        List<UserInfoJavaModel> tempList = new ArrayList<UserInfoJavaModel>();
        ResultJavaEntity resultJavaEntity = null;
        for (UserInfoJavaModel user : usersToSyncUpdate) {
            tempList.add(user);

            try {
                resultJavaEntity = userService.users(islink, tempList, apikey, secretkey, baseUrl);
                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    // 忽略邮箱再同步一次
                    user.setMail(null);
                    tempList.set(0, user);
                    resultJavaEntity = userService.users(islink, tempList, apikey, secretkey, baseUrl);
                    if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                        printLog("用户同步[" + syncServiceName + "]失败 ", user.getId(), resultJavaEntity);
                    }
                }
            } catch (IOException e) {
                LOGGER.error("用户同步[" + syncServiceName + "]失败 " + user.getId(), e);
            }

            tempList.clear();
        }

        // 增加设置直属经理
        syncSetUserManagerNoOneByOne(usersToSyncUpdate);
    }

    /**
     * 逐个用户设置直属经理
     *
     * @param usersToSyncUpdate
     */
    protected void syncSetUserManagerNoOneByOne(List<UserInfoJavaModel> usersToSyncUpdate) {
        List<UserInfoJavaModel> tempList = new ArrayList<UserInfoJavaModel>();
        ResultJavaEntity resultJavaEntity = null;
        for (UserInfoJavaModel user : usersToSyncUpdate) {
            try {
                // 设置直属经理
                String managerNo = user.getManagerNo();
                if (StringUtils.isNotBlank(managerNo)) {
                    tempList.set(0, user);
                    resultJavaEntity = userService.addmgr(tempList, apikey, secretkey,baseUrl);
                    if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                        LOGGER.error("设置直属经理失败：" + resultJavaEntity.getMsg());
                    }

                    tempList.clear();
                }
            } catch (IOException e) {
                LOGGER.error("设置直属经理[" + syncServiceName + "]失败 " + user.getId(), e);
            }
        }
    }

    /**
     * 逐个用户同步禁用
     *
     * @param usersToDisable
     * @param ifPringLog
     */
    protected void syncDisableUserOneByOne(List<UserInfoJavaModel> usersToDisable, boolean ifPringLog) {
        List<String> tempList = new ArrayList<String>();
        ResultJavaEntity resultJavaEntity = null;
        for (UserInfoJavaModel user : usersToDisable) {
            // 用户名是admin时忽略
            String userName = user.getUserName();
            if ("admin".equals(userName)) {
                continue;
            }

            tempList.add(userName);

            try {
                resultJavaEntity = userService.disabledusers(tempList, apikey, secretkey, baseUrl);
                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    if (ifPringLog) {
                        printLog("用户同步[" + syncServiceName + "]禁用失败 ", user.getId(), resultJavaEntity);
                    }
                }
            } catch (IOException e) {
                LOGGER.error("用户同步[" + syncServiceName + "]禁用失败 " + user.getId(), e);
            }

            tempList.clear();
        }
    }

    /**
     * 逐个用户同步删除（用户被删除后学习记录等数据会被清空且不可恢复，已改为禁用）
     *
     * @param usersToDelete
     * @param ifPringLog
     */
    protected void syncDeleteUserOneByOne(List<UserInfoJavaModel> usersToDelete, boolean ifPringLog) {
        List<String> tempList = new ArrayList<String>();
        ResultJavaEntity resultJavaEntity = null;
        for (UserInfoJavaModel user : usersToDelete) {
            // 用户名是admin时忽略不删除
            String userName = user.getUserName();
            if ("admin".equals(userName)) {
                continue;
            }

            tempList.add(userName);

            try {
                resultJavaEntity = userService.deletedusers(tempList, apikey, secretkey, baseUrl);
                if (SYNC_RESULT_SUCCESS != resultJavaEntity.getResult()) {
                    if (ifPringLog) {
                        printLog("用户同步[" + syncServiceName + "]删除失败 ", user.getId(), resultJavaEntity);
                    }
                }
            } catch (IOException e) {
                LOGGER.error("用户同步[" + syncServiceName + "]删除失败 " + user.getId(), e);
            }

            tempList.clear();
        }
    }

    /**
     * 通过复制属性值的方法将数据模型集合转换为同步用的对象集合
     *
     * @param fromList        数据模型集合
     * @param toListClassType 复制目标对象的类型
     * @return 复制后的对象集合
     * @throws ReflectiveOperationException
     */
    protected <E, T> List<T> copyCreateEntityList(List<E> fromList, Class<T> toListClassType)
            throws ReflectiveOperationException {
        List<T> entityList = null;

        if (fromList != null) {
            int listSize = fromList.size();
            entityList = new ArrayList<T>(listSize);

            for (int i = 0; i < listSize; i++) {
                T instance = toListClassType.newInstance();
                BeanUtils.copyProperties(instance, fromList.get(i));
                entityList.add(instance);
            }
        }

        return entityList;
    }

    /**
     * 计算得到昨天的日期
     *
     * @param date
     * @return
     */
    protected Date getYesterdayDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        // 修改为返回三天前的日期，防止出现异常造成单日数据漏同步
        c.add(Calendar.DAY_OF_MONTH, -3);
        return c.getTime();
    }

    /**
     * 同步返回错误信息日志记录
     *
     * @param type
     * @param errKey
     * @param resultJavaEntity
     */
    protected void printLog(String type, String errKey, ResultJavaEntity resultJavaEntity) {
        LOGGER.error(type + "ID：" + errKey + " 错误信息：" + resultJavaEntity.getResult() + "-" + resultJavaEntity.getMsg());
    }

    /**
     * 从数据库获取岗位数据
     *
     * @return
     * @throws Exception
     */
    protected abstract List<PositionJavaModel> getPositionsFromDB() throws Exception;

    /**
     * 从数据库获取组织数据
     *
     * @return
     * @throws Exception
     */
    protected abstract List<OuInfoJavaModel> getOuInfoListFromDB() throws Exception;

    /**
     * 从数据库获取人员数据
     *
     * @return
     * @throws Exception
     */
    protected abstract List<UserInfoJavaModel> getUserInfoListFromDB() throws Exception;

    /**
     * 判断组织是否过期.同步删除组织时用
     *
     * @param org
     * @return
     */
    protected abstract boolean isOrgExpired(OuInfoJavaModel org);

    /**
     * 判断岗位是否过期.同步删除岗位时用
     *
     * @param pos
     * @return
     */
    protected abstract boolean isPosExpired(PositionJavaModel pos);

    /**
     * 判断用户是否过期.同步禁用或删除人员时用
     *
     * @param user
     * @return
     */
    protected abstract boolean isUserExpired(UserInfoJavaModel user);

    /**
     * 设置根组织的父节点id为null
     *
     * @param newList
     */
    protected abstract void setRootOrgParentId(List<OuInfoJavaModel> newList);

    /**
     * 根据实际情况更改属性值
     *
     * @param newList
     */
    protected abstract void changePropValues(List<UserInfoJavaModel> newList);

    /**
     * 调用客户接口获取组织对象集合，注意全量增量区分。组织不同步返回new ArrayList<>(0);
     *
     * @param mode 全量增量区分
     * @return 全量或者增量组织对象集合
     */
    protected abstract List<OuInfoJavaModel> getOuInfoModelList(String mode) throws Exception;

    /**
     * 调用客户接口获取岗位对象集合，注意全量增量区分。岗位不同步返回new ArrayList<>(0);
     *
     * @param mode 全量增量区分
     * @return 全量或者增量岗位对象集合
     */
    protected abstract List<PositionJavaModel> getPositionModelList(String mode) throws Exception;

    /**
     * 调用客户接口获取用户对象集合，注意全量增量区分。用户不同步返回new ArrayList<>(0);
     *
     * @param mode 全量增量区分
     * @return 全量或者增量用户对象集合
     */
    protected abstract List<UserInfoJavaModel> getUserInfoModelList(String mode) throws Exception;


}
