package com.crm.manager.service.impl;

import com.alibaba.fastjson.JSON;
import com.crm.manager.dao.mapper.UserInfoDao;
import com.crm.manager.dao.repository.*;
import com.crm.manager.property.GooleUserAdminApiProperty;
import com.crm.manager.service.*;
import com.crm.manager.service.custom.CustomInfoFeignService;
import com.crm.manager.service.task.TradeSaleCommissionFeignService;
import com.crm.rely.backend.core.constant.*;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.BaseResultWithPagerDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.sales.SalesBalanceDto;
import com.crm.rely.backend.core.dto.user.department.UserDepartmentSearchDto;
import com.crm.rely.backend.core.dto.user.info.*;
import com.crm.rely.backend.core.dto.user.role.UserRoleDto;
import com.crm.rely.backend.core.entity.custom.info.IbInfoEntity;
import com.crm.rely.backend.core.entity.custom.info.InfoEntity;
import com.crm.rely.backend.core.entity.custom.login.CustomLoginStatusUpdateBySalesIdEntity;
import com.crm.rely.backend.core.entity.custom.login.delete.CustomLoginDeleteExcludeAddEntity;
import com.crm.rely.backend.core.entity.login.BaseLoginEntity;
import com.crm.rely.backend.core.entity.sys.SysSalesLoginAddEntity;
import com.crm.rely.backend.core.entity.system.email.SysEmailSendEntity;
import com.crm.rely.backend.core.entity.tenant.info.TenantRespEntity;
import com.crm.rely.backend.core.entity.user.info.*;
import com.crm.rely.backend.core.entity.user.role.UserRoleUpdateNumberEntity;
import com.crm.rely.backend.core.pojo.table.*;
import com.crm.rely.backend.core.pojo.view.UserInfoView;
import com.crm.rely.backend.exception.DataNotFoundException;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.EmailService;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.service.RedisService;
import com.crm.rely.backend.util.*;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @program: crm-backend
 * @description:
 * @author: houn
 * @create: 2019-07-25 16:14
 */
@Log4j
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private SysUserLoginHistoryRepository sysUserLoginHistoryRepository;

    @Autowired
    private CustomInfoFeignService customInfoFeignService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private UserDepartmentService userDepartmentService;

    @Autowired
    private UserGroupRepository userGroupRepository;

    @Autowired
    private AgentLevelRepository agentLevelRepository;

    @Autowired
    private RedisService redisService;

    @Autowired
    private MqSendService mqSendService;

    @Autowired
    private CustomLoginService customLoginService;

    @Autowired
    private SysIpLimitService sysIpLimitService;

    @Autowired
    private TradeSaleCommissionFeignService tradeSaleCommissionFeignService;

    @Autowired
    private EmailService emailService;


    @Autowired
    private Environment environment;

    @Value("${role.googleVerified:false}")
    private boolean googleVerified;

    @Autowired
    private SalesSalaryRecordService salesSalaryRecordService;

    @Autowired
    private SysSalesLoginService sysSalesLoginService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private CustomLoginDeleteExcludeService customLoginDeleteExcludeService;
    @Autowired
    private SysGoogleGroupEmailRepository sysGoogleGroupEmailRepository;
    @Autowired
    private SysRemitExcludeCidRepository sysRemitExcludeCidRepository;
    @Autowired
    private CustomLoginRepository customLoginRepository;
    @Autowired
    private UserInfoAttachService userInfoAttachService;

    /**
     * 用户登录
     *
     * @param entity
     * @return
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer loginValid(UserLoginValidEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstByUsernameAndPassword(entity.getLoginName(),
                entity.getPassword());

        if (userInfoTable == null) {
            throw new ServiceException(Constants.LOGIN_FAIL);
        }

        return userInfoTable.getVerified();
    }

    @Override
    public InfoEntity login(UserLoginEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstByUsernameAndPassword(entity.getLoginName(),
                entity.getPassword());

        if (userInfoTable == null) {
            throw new ServiceException(Constants.LOGIN_FAIL);
        }
        limitIp(entity.getIp(), userInfoTable);

//        if (googleVerified) {
//            if (userInfoTable.getVerified() != null && userInfoTable.getVerified().equals(1)) {
//                loginValidateGoogleAuthenticatorCode(userInfoTable, entity.getGaCode());
//            }
//
//        } else {
//            if (!Strings.isNullOrEmpty(entity.getEmailCode())) {
//                loginValidateCode(userInfoTable.getEmail(), entity.getEmailCode());
//            } else if (entity.getGaCode() != null) {
//                loginValidateGoogleAuthenticatorCode(userInfoTable, entity.getGaCode());
//            } else {
//                throw ServiceException.exception(Constants.SYSTEM_ERROR);
//            }
//        }
        validCode(entity, userInfoTable);


//        if (userInfoTable.getWithdrawCId() != null || userInfoTable.getCustomId() != null) {
//            throw ServiceException.exception(Constants.NOT_PERMIT);
//        }
        if (userInfoTable.getRoleId() != null && userInfoTable.getRoleId().equals(-1)) {
            throw ServiceException.exception(Constants.NOT_PERMIT);
        }
        if (userInfoTable.getValid() == null || !userInfoTable.getValid().equals(1)) {
            throw ServiceException.exception(Constants.RESTRICTED_LOGIN);
        }
        UserRoleDto userRoleDto;
        UserDepartmentSearchDto userDepartmentSearchDto;
        if (userInfoTable.getRoleId() != null) {
            userRoleDto = userRoleService.getRoleInfo(userInfoTable.getRoleId());
            if (userRoleDto == null) {
                throw ServiceException.exception(Constants.SYSTEM_ERROR);
            }
            userDepartmentSearchDto = userDepartmentService.searchSingle(userRoleDto.getDepartmentId());
            if (userDepartmentSearchDto == null) {
                throw ServiceException.exception(Constants.SYSTEM_ERROR);
            }
        } else {
            userRoleDto = null;
            userDepartmentSearchDto = null;
        }
        userInfoTable.setLastAddress(entity.getAddress());
        userInfoTable.setLastIp(entity.getIp());
        userInfoTable.setLastTime(entity.getTime());
        UserGroupTable userGroupTable = null;
        if (userInfoTable.getGroupId() != null && userInfoTable.getGroupId() > 0) {
            userGroupTable = userGroupRepository.getFirstById(userInfoTable.getGroupId());
        }

        if (userInfoTable.getVerified() == null) {
            userInfoTable.setVerified(0);
        }

        InfoEntity infoEntity = transform(userInfoTable, entity, userRoleDto, userDepartmentSearchDto,
                userGroupTable);

        /**
         * 更新登录信息
         */
        userInfoRepository.save(userInfoTable);

        try {
            SysUserLoginHistoryTable sysUserLoginHistoryTable = new SysUserLoginHistoryTable();
            sysUserLoginHistoryTable.setAddress(entity.getAddress());
            sysUserLoginHistoryTable.setLoginIp(entity.getIp());
            sysUserLoginHistoryTable.setLoginUser(userInfoTable.getId());
            sysUserLoginHistoryTable.setLoginTime(entity.getTime());
            sysUserLoginHistoryRepository.save(sysUserLoginHistoryTable);
        } catch (Exception e) {
            e.getStackTrace();
        }

        return infoEntity;
    }

    @Override
    public InfoEntity loginByAttachId(UserAttachLoginEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.getOne(entity.getAttachId());

        if (userInfoTable == null) {
            throw new ServiceException(Constants.LOGIN_FAIL);
        }
        if (userInfoTable.getRoleId() != null && userInfoTable.getRoleId().equals(-1)) {
            throw ServiceException.exception(Constants.NOT_PERMIT);
        }
        if (userInfoTable.getValid() == null || !userInfoTable.getValid().equals(1)) {
            throw ServiceException.exception(Constants.RESTRICTED_LOGIN);
        }
        UserRoleDto userRoleDto;
        UserDepartmentSearchDto userDepartmentSearchDto;
        if (userInfoTable.getRoleId() != null) {
            userRoleDto = userRoleService.getRoleInfo(userInfoTable.getRoleId());
            if (userRoleDto == null) {
                throw ServiceException.exception(Constants.SYSTEM_ERROR);
            }
            userDepartmentSearchDto = userDepartmentService.searchSingle(userRoleDto.getDepartmentId());
            if (userDepartmentSearchDto == null) {
                throw ServiceException.exception(Constants.SYSTEM_ERROR);
            }
        } else {
            userRoleDto = null;
            userDepartmentSearchDto = null;
        }
        userInfoTable.setLastAddress(entity.getAddress());
        userInfoTable.setLastIp(entity.getIp());
        userInfoTable.setLastTime(entity.getTime());
        UserGroupTable userGroupTable = null;
        if (userInfoTable.getGroupId() != null && userInfoTable.getGroupId() > 0) {
            userGroupTable = userGroupRepository.getFirstById(userInfoTable.getGroupId());
        }

        if (userInfoTable.getVerified() == null) {
            userInfoTable.setVerified(0);
        }

        InfoEntity infoEntity = transform(userInfoTable, entity, userRoleDto, userDepartmentSearchDto,
                userGroupTable);

        /**
         * 更新登录信息
         */
        userInfoRepository.save(userInfoTable);

        try {
            SysUserLoginHistoryTable sysUserLoginHistoryTable = new SysUserLoginHistoryTable();
            sysUserLoginHistoryTable.setAddress(entity.getAddress());
            sysUserLoginHistoryTable.setLoginIp(entity.getIp());
            sysUserLoginHistoryTable.setLoginUser(userInfoTable.getId());
            sysUserLoginHistoryTable.setLoginTime(entity.getTime());
            sysUserLoginHistoryRepository.save(sysUserLoginHistoryTable);
        } catch (Exception e) {
            e.getStackTrace();
        }

        return infoEntity;
    }

    @Override
    public void loginSendCode(UserLoginSendEmailCodeEntity entity) throws ServiceException {
        UserInfoTable userInfoTable = userInfoRepository.getFirstByUsername(entity.getLoginName());
        if (userInfoTable == null) {
            throw new ServiceException(Constants.RESTRICTED_LOGIN);
        }
        entity.setEmail(userInfoTable.getEmail().toLowerCase());
        //构建实体
        SysEmailSendEntity sysEmailSendEntity = createLoginSendEmailSysEmailEntity(entity);

        //发送收据
        emailService.sendCode(sysEmailSendEntity, sysEmailSendEntity.getMap().get(MapConstants.CODE) +
                "loginSendCode");
    }

    @Override
    public void loginValidateCode(String email, String emailCode) throws ServiceException {
        for (int i = 0; i < environment.getActiveProfiles().length; i++) {
            if (environment.getActiveProfiles()[i].equals("prod")) {
                emailService.validateCode(email, emailCode +
                        "loginSendCode");
                break;
            }
        }
    }

    @Override
    public void loginValidateGoogleAuthenticatorCode(UserInfoTable user, Integer code) throws ServiceException {
        for (int i = 0; i < environment.getActiveProfiles().length; i++) {
            if (environment.getActiveProfiles()[i].equals("prod")) {
                if (user.getVerified() == null || !user.getVerified().equals(1)) {
                    throw ServiceException.exception(Constants.GOOGLE_SECRET_NOT_BIND_ERROR);
                }
                if (Strings.isNullOrEmpty(user.getSecretKey())) {
                    throw ServiceException.exception(Constants.GOOGLE_SECRET_NOT_EXIST_ERROR);
                }

                if (code == null || !GoogleAuthenticatorUtil.verifyCode(user.getSecretKey(), code)) {
                    throw ServiceException.exception(Constants.GOOGLE_CAPTCHA_ERROR);
                }
                break;
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserInfoGoogleSecretKeyDto getGoogleSecretKey(Long id) throws ServiceException {
        UserInfoTable userInfoTable = findById(id);

        if (Strings.isNullOrEmpty(userInfoTable.getSecretKey())) {
            userInfoTable.setSecretKey(GoogleAuthenticatorUtil.generateSecretKey());

            userInfoRepository.save(userInfoTable);
        }

        UserInfoGoogleSecretKeyDto userInfoGoogleSecretKeyDto = new UserInfoGoogleSecretKeyDto();

        userInfoGoogleSecretKeyDto.setSecretKey(userInfoTable.getSecretKey());
        userInfoGoogleSecretKeyDto.setQrUrl(GoogleAuthenticatorUtil.getOtpAuthURL(userInfoTable.getSecretKey(),
                userInfoTable.getUsername()));

        return userInfoGoogleSecretKeyDto;
    }

    /**
     * 绑定谷歌验证码
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bind(UserInfoBindEntity entity) throws ServiceException {
        UserInfoTable userInfoTable = findById(entity.getId());

        if (Strings.isNullOrEmpty(userInfoTable.getSecretKey())) {
            throw ServiceException.exception(Constants.GOOGLE_SECRET_NOT_EXIST_ERROR);
        }
        if (GoogleAuthenticatorUtil.verifyCode(userInfoTable.getSecretKey(), entity.getGaCode())) {
            userInfoTable.setVerified(1);
            userInfoRepository.save(userInfoTable);
        } else {
            throw ServiceException.exception(Constants.GOOGLE_CAPTCHA_ERROR);
        }
    }

    /**
     * 清理谷歌密钥 但不解除绑定
     *
     * @param id
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeSecretKey(Long id) throws ServiceException {
        UserInfoTable userInfoTable = findById(id);
        userInfoTable.setSecretKey(null);
        userInfoRepository.save(userInfoTable);
    }

    /**
     * 重置密钥 后续重新绑定
     *
     * @param id
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reSecretKey(Long id) throws ServiceException {
        UserInfoTable userInfoTable = findById(id);
        userInfoTable.setSecretKey(null);
        userInfoTable.setVerified(0);
        userInfoRepository.save(userInfoTable);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBalance(Long id, Float amount) throws ServiceException {
        try {
            UserInfoTable userInfoTable = userInfoRepository.findOne(id);
            if (userInfoTable.getBalance() == null) {
                userInfoTable.setBalance(0F);
            }
            userInfoTable.setBalance(userInfoTable.getBalance() + amount);
            userInfoDao.updateUserBalanceById(userInfoTable);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
        }


    }

    @Override
    public SalesBalanceDto getSalesBalanceById(Long id) throws ServiceException {

        UserInfoTable userInfoTable = userInfoDao.getDataById(id);
        if (userInfoTable == null) {
            throw new ServiceException(Constants.INFO_NOT_FOUND);
        }
        SalesBalanceDto dto = SalesBalanceDto.getInstance();
        dto.setBalance(userInfoTable.getBalance() == null ? 0F : userInfoTable.getBalance());
        dto.setSalaryLogin(userInfoTable.getSalaryLogin());
        dto.setSalaryPlatform(userInfoTable.getSalaryPlatform());
        return dto;
    }

    @Override
    public List<UserInfoTreeDto> getUserInfoTree() throws ServiceException {


        try {
            Long roleId = userRoleService.getIdByRoleCode("ROLE_SALE");
            if (roleId == null) {
                return Lists.newArrayList();
            }

            List<UserInfoTreeDto> dtos = new ArrayList<>();

            UserInfoTable systemuser = userInfoDao.getDataByEmail("systemuser");
            UserInfoTreeDto systemUserDtgo = new UserInfoTreeDto();
            systemUserDtgo.setId(systemuser.getId());
            systemUserDtgo.setPid(0L);
            systemUserDtgo.setIbNo(systemuser.getIbNo());
            systemUserDtgo.setName(systemuser.getName());
            systemUserDtgo.setIbNoTemp(systemuser.getIbNoTemp());
            dtos.add(systemUserDtgo);

            List<UserInfoTable> tables = userInfoDao.getDataByRoleId(roleId);
            tables.forEach(table -> {
                UserInfoTreeDto dto = new UserInfoTreeDto();
                dto.setId(table.getId());
                dto.setPid(table.getPid());
                dto.setIbNo(table.getIbNo());
                dto.setName(table.getName());
                dto.setIbNoTemp(table.getIbNoTemp());
                dtos.add(dto);
            });

            return dtos;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    private SysEmailSendEntity createLoginSendEmailSysEmailEntity(UserLoginSendEmailCodeEntity entity) {
        SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();

        Map<String, String> map = new HashMap<>(2);
        String code = GetRandom.getRandom(6);
        map.put(MapConstants.CODE, code);
        Date time = DateUtil.operationMinute(new Date(), Constants.EMAIL_VALIDATECODE_TIME);
        map.put(MapConstants.EXPIRE_TIME, DateUtil.formatTime(time));
        map.put(MapConstants.DATE_TIME, DateUtil.formatTime());

        sysEmailSendEntity.setAddIp(entity.getIp());
        sysEmailSendEntity.setAddTime(entity.getTime());

        sysEmailSendEntity.setUsers(entity.getEmail());
        sysEmailSendEntity.setEmailSendEnum(EmailSendEnum.USER_LOGIN_SEND);
        if ("cn".equals(entity.getLang())) {
            sysEmailSendEntity.setTemplateName(SystemEmailCodeConstants.USER_LOGIN_SEND_CN);
        } else {
            sysEmailSendEntity.setTemplateName(SystemEmailCodeConstants.USER_LOGIN_SEND_EN);
        }
        sysEmailSendEntity.setMap(map);

        return sysEmailSendEntity;
    }

    /**
     * 添加用户信息
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized UserInfoTable add(UserInfoAddEntity entity) throws Exception {

        //判断角色是否存在
        userRoleService.existRole(entity.getRoleId());
        UserRoleTable roleTable = userRoleService.findRoleInfo(entity.getRoleId());
        if(roleTable.getMerchantId() != null){
            entity.setMerchantId(roleTable.getMerchantId());
        }
        //用户名
        existByUsername(entity.getUsername());

        //邮箱
        existByEmail(entity.getEmail());

        UserInfoTable userInfoTable = new UserInfoTable();
        BeanUtils.copyProperties(entity, userInfoTable);

        userInfoTable.setCId(CidUtil.getCid().longValue());
        userInfoTable.setCustomId(null);

        /*
            判断角色
         */
        Long roleId = userInfoTable.getRoleId();
        String roleCode = userRoleService.getRoleCodeById(roleId);
        if ("ROLE_SALE".equalsIgnoreCase(roleCode)) {
            if (userInfoTable.getPid() == null || userInfoTable.getPid() <= 0) {
                //获取超级管理员ID
//                UserInfoTable superAdmin = userInfoDao.getSuperAdminInfo();
//                userInfoTable.setPid(superAdmin.getId());
//                userInfoTable.setPStamp(superAdmin.getStamp());
//                userInfoTable.setSalesShare(1F);
                throw new ServiceException(Constants.NOT_PERMIT);
            } else {
                //获取上级信息
                UserInfoTable superUser = userInfoRepository.getOne(userInfoTable.getPid());
                userInfoTable.setPStamp(superUser.getStamp());
                userInfoTable.setSalesShare((superUser.getSalesShare() == null || superUser.getSalesShare() <= 0) ?
                        1F : superUser.getSalesShare());
                if (Strings.isNullOrEmpty(superUser.getExcludeShowLoginTypes())) {
                    userInfoTable.setExcludeShowLoginTypes("5,6");
                } else {
                    userInfoTable.setExcludeShowLoginTypes(superUser.getExcludeShowLoginTypes());
                }
            }
            //生成stamp
            String stamp = getStampByPId(userInfoTable.getPid());
            userInfoTable.setStamp(stamp);

        } else {
            userInfoTable.setStamp("01");
            userInfoTable.setIdStamp("01");
        }

        SysConfigTable gogleConfigTable = sysConfigService.getByCode(ConfigConstants.GOOGLE_USER_ADMIN_API_PROPERTY);
        if (gogleConfigTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }

        //谷歌账户添加
        for (int i = 0; i < environment.getActiveProfiles().length; i++) {
            if (environment.getActiveProfiles()[i].equals("prod")) {
                if (!Strings.isNullOrEmpty(entity.getGroupEmail())) {
                    GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(),
                            GooleUserAdminApiProperty.class);
                    String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(),
                            property.getClientEmail(), property.getPrivateKey());

                    String[] emails = entity.getGroupEmail().split(",");
                    for (String email : emails) {
                        Integer groupCode = GoogleAdminAPIHttp.addUserToGroup(accessToken, email,
                                userInfoTable.getEmail(),
                                null);
                        if (Constants.SUCCESS_CODE != groupCode) {
                            throw ServiceException.exception("create GoogleEmail Group is error");
                        }
                    }
                    break;
                }
            }
        }

        //薪资账户
        SysSalesLoginAddEntity sysSalesLoginAddEntity = new SysSalesLoginAddEntity();
        sysSalesLoginAddEntity.setLogin(entity.getSalaryLogin());
        sysSalesLoginAddEntity.setIbNo(entity.getIbNo());
        sysSalesLoginAddEntity.setAddTime(entity.getAddTime());
        sysSalesLoginService.addFromUserInfo(sysSalesLoginAddEntity);

        String secretKeyv = GoogleAuthenticatorUtil.generateSecretKey();
        userInfoTable.setSecretKey(secretKeyv);
        userInfoTable.setVerified(0);
        userInfoTable.setAgentAccountSetting(1);
        userInfoTable.setAgentAccountSettings("1");
        userInfoTable.setFixedHide(0);
        userInfoTable = userInfoRepository.save(userInfoTable);
        /*
            如果是销售更新销售ID
         */
        if ("ROLE_SALE".equalsIgnoreCase(roleCode)) {
            userInfoTable.setSalesId(userInfoTable.getId());
            userInfoTable.setIdStamp(getIdStamp(userInfoTable.getId(), userInfoTable.getPid()));
            userInfoRepository.save(userInfoTable);
        }
        UserRoleUpdateNumberEntity userRoleUpdateNumberEntity = new UserRoleUpdateNumberEntity();
        userRoleUpdateNumberEntity.setId(entity.getRoleId());
        userRoleUpdateNumberEntity.setChangeNumber(1);
        userRoleService.updateNumber(userRoleUpdateNumberEntity);

        if ("ROLE_SALE".equalsIgnoreCase(roleCode)) {
            SysRemitExcludeCidTable cidTable = new SysRemitExcludeCidTable();
            cidTable.setUserId(userInfoTable.getId());
            cidTable.setCId(userInfoTable.getCId());
            sysRemitExcludeCidRepository.save(cidTable);
        }

        if (null != userInfoTable.getSalaryLogin()) {
            CustomLoginDeleteExcludeAddEntity excludeAddEntity = new CustomLoginDeleteExcludeAddEntity();
            excludeAddEntity.setLogin(userInfoTable.getSalaryLogin());
            excludeAddEntity.setPlatform(userInfoTable.getSalaryPlatform());
            customLoginDeleteExcludeService.add(excludeAddEntity);

            CustomLoginTable loginTable =
                    customLoginRepository.getCustomLoginByLoginAndPlatform(userInfoTable.getSalaryLogin(),
                            userInfoTable.getSalaryPlatform());
            if (null != loginTable) {
                SysRemitExcludeCidTable loginCidTable = new SysRemitExcludeCidTable();
                loginCidTable.setUserId(userInfoTable.getId());
                loginCidTable.setCId(loginTable.getCId());
                loginCidTable.setLogin(loginTable.getLogin());
                loginCidTable.setPlatform(loginTable.getPlatform());
                sysRemitExcludeCidRepository.save(loginCidTable);
            }

        }

        return userInfoTable;
    }

    /**
     * 删除用户
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(UserInfoDeleteEntity entity) throws ServiceException {


        List<UserInfoTable> userInfoTables = userInfoRepository.findAll(entity.getIds());
        if (userInfoTables == null || userInfoTables.size() <= 0) {
            return;
        }

        //判断是否有下级，如果有则不能删除
        if (subUserExists(userInfoTables)) {
            throw new ServiceException("存在下级，不能删除");
        }

        userInfoRepository.delete(userInfoTables);

        List<UserRoleUpdateNumberEntity> userRoleUpdateNumberEntities = new ArrayList<>(userInfoTables.size());
        userInfoTables.forEach(value -> {
            if (value.getRoleId() != null) {
                UserRoleUpdateNumberEntity userRoleUpdateNumberEntity = new UserRoleUpdateNumberEntity();
                userRoleUpdateNumberEntity.setId(value.getRoleId());
                userRoleUpdateNumberEntity.setChangeNumber(-1);
                userRoleUpdateNumberEntities.add(userRoleUpdateNumberEntity);
            }
        });
        if (userRoleUpdateNumberEntities != null && userRoleUpdateNumberEntities.size() > 0) {

            userRoleService.updateNumber(userRoleUpdateNumberEntities);
        }

        sysRemitExcludeCidRepository.deleteAllByUserIdIn(entity.getIds());


    }

    private boolean subUserExists(List<UserInfoTable> userInfoTables) {
        boolean exists = false;
        for (UserInfoTable userInfoTable : userInfoTables) {
            Integer count = userInfoRepository.countByPid(userInfoTable.getId());
            if (count != null && count >= 1) {
                exists = true;
                break;
            }
        }

        return exists;
    }

    /**
     * 修改用户信息
     *
     * @param entity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized UserInfoTable update(UserInfoUpdateEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstById(entity.getId());

        if (userInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        List<UserRoleUpdateNumberEntity> userRoleUpdateNumberEntities = null;
        //角色
        if (!entity.getRoleId().equals(userInfoTable.getRoleId())) {
            userRoleService.existRole(entity.getRoleId());

            userRoleUpdateNumberEntities = new ArrayList<>(2);
            UserRoleUpdateNumberEntity userRoleUpdateNumberEntityOld = new UserRoleUpdateNumberEntity();
            userRoleUpdateNumberEntityOld.setId(userInfoTable.getRoleId());
            userRoleUpdateNumberEntityOld.setChangeNumber(-1);
            userRoleUpdateNumberEntities.add(userRoleUpdateNumberEntityOld);

            UserRoleUpdateNumberEntity userRoleUpdateNumberEntityNew = new UserRoleUpdateNumberEntity();
            userRoleUpdateNumberEntityNew.setId(entity.getRoleId());
            userRoleUpdateNumberEntityNew.setChangeNumber(1);
            userRoleUpdateNumberEntities.add(userRoleUpdateNumberEntityNew);

        }

        //用户名
        if (!entity.getUsername().equals(userInfoTable.getUsername())) {
            existByUsername(entity.getUsername());
        }

        //邮箱
        if (!entity.getEmail().toLowerCase().equals(userInfoTable.getEmail().toLowerCase())) {
            existByEmail(entity.getEmail());
        }

        if (Strings.isNullOrEmpty(entity.getPassword())) {
            entity.setPassword(userInfoTable.getPassword());
        }

        /*
            上级发生变动
         */
        //新上级
        UserInfoTable pUser = null;
        if (entity.getPid() != null) {
            pUser = userInfoRepository.getFirstById(entity.getPid());
        }
        if (entity.getPid() != null && pUser == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }
        if (pUser != null && !pUser.getId().equals(userInfoTable.getPid())) {
            //获取名下所有销售和代理
            List<UserInfoTable> subs = userInfoDao.findAllByStamp(userInfoTable.getStamp());
            //获取新上级名下最大的stamp
            String maxStamp = userInfoDao.getMaxStampByPid(entity.getPid());
            if (maxStamp == null) {
                maxStamp = pUser.getStamp() + "00";
            }
            userInfoTable.setStamp(StampUtil.getStamp(maxStamp));
            userInfoTable.setPStamp(pUser.getStamp());
            userInfoTable.setIdStamp(StampUtil.formatIdStamp(userInfoTable.getId(), pUser.getIdStamp()));

            if (!CollectionUtils.isEmpty(subs)) {
                //调整名下代理stamp和pStamp
                setSubsStamp(subs, userInfoTable.getStamp() + "00", userInfoTable);
                //批量更新下级的stamp和pStamp
                userInfoDao.updateUserStampByBatch(subs);
            }
            //批量更新客户代理信息的状态，用于同步manager备注
            CustomLoginStatusUpdateBySalesIdEntity salesIdEntity = new CustomLoginStatusUpdateBySalesIdEntity();
            salesIdEntity.setModifyIp(entity.getModifyIp());
            salesIdEntity.setModifyTime(entity.getModifyTime());
            salesIdEntity.setModifyUser(entity.getModifyUser());
            salesIdEntity.setSalesId(userInfoTable.getPid());
            customLoginService.updateLoginStatusBySalesId(salesIdEntity);

        }

        //薪资账户
        SysSalesLoginAddEntity sysSalesLoginAddEntity = new SysSalesLoginAddEntity();
        sysSalesLoginAddEntity.setLogin(entity.getSalaryLogin());
        sysSalesLoginAddEntity.setIbNo(entity.getIbNo());
        sysSalesLoginAddEntity.setAddTime(entity.getModifyTime());
        sysSalesLoginService.addFromUserInfo(sysSalesLoginAddEntity);

        /*
            单账户关联
         */
        Long attachId = entity.getAttachId();
        if (attachId != null && attachId > 0) {
            List<UserInfoTable> attachedUsers = userInfoRepository.findAllByAttachId(userInfoTable.getId());
            if (CollectionUtils.isEmpty(attachedUsers)) {
                UserInfoTable attachUser = userInfoRepository.getOne(attachId);
                if (attachUser != null) {
                    attachUser.setAttachId(userInfoTable.getId());
                    userInfoRepository.save(attachUser);
                }
            } else {
                userInfoTable.setAttachId(null);
            }
        }
        /*
            多账户关联
         */
//        userInfoAttachService.saveAttachInfo(userInfoTable.getId(), entity.getAttachIds());


        BeanUtils.copyProperties(entity, userInfoTable);
        userInfoRepository.save(userInfoTable);

        if (userRoleUpdateNumberEntities != null) {
            userRoleService.updateNumber(userRoleUpdateNumberEntities);
        }

        sysRemitExcludeCidRepository.deleteByUserIdAndLoginIsNotNull(userInfoTable.getId());
        if (null != userInfoTable.getSalaryLogin()) {
            CustomLoginDeleteExcludeAddEntity excludeAddEntity = new CustomLoginDeleteExcludeAddEntity();
            excludeAddEntity.setLogin(userInfoTable.getSalaryLogin());
            excludeAddEntity.setPlatform(userInfoTable.getSalaryPlatform());
            customLoginDeleteExcludeService.add(excludeAddEntity);

            CustomLoginTable loginTable =
                    customLoginRepository.getCustomLoginByLoginAndPlatform(userInfoTable.getSalaryLogin(),
                            userInfoTable.getSalaryPlatform());
            if (null != loginTable) {
                SysRemitExcludeCidTable loginCidTable = new SysRemitExcludeCidTable();
                loginCidTable.setUserId(userInfoTable.getId());
                loginCidTable.setCId(loginTable.getCId());
                loginCidTable.setLogin(loginTable.getLogin());
                loginCidTable.setPlatform(loginTable.getPlatform());
                sysRemitExcludeCidRepository.save(loginCidTable);
            }
        }

        return userInfoTable;

    }

    public void setSubsStamp(List<UserInfoTable> subs, String maxNo, UserInfoTable parent) {
        for (UserInfoTable sub : subs) {
            if (sub.getPid().equals(parent.getId())) {
                maxNo = StampUtil.getStamp(maxNo);
                sub.setStamp(maxNo);
                sub.setPStamp(parent.getStamp());
                sub.setIdStamp(StampUtil.formatIdStamp(sub.getId(), parent.getIdStamp()));
                setSubsStamp(subs, sub.getStamp() + "00", sub);
            }
        }
    }


    /**
     * 根据条件搜索列表
     *
     * @param entity
     * @return
     * @throws ServiceException
     */
    @Override
    public BaseResultWithPagerDto<List<UserInfoSearchDto>> searchPage(UserInfoSearchEntity entity) throws ServiceException {

        Integer count = userInfoDao.searchByPageCount(entity);
        PageDto pageDto = PageDto.format(entity, count);
        if (count == null || count <= 0) {
            return ResultWithPagerDto.success(pageDto);
        }
        List<UserInfoView> userInfoViews = userInfoDao.searchByPageList(entity);

        if (userInfoViews == null || userInfoViews.size() <= 0) {

            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        List<UserInfoSearchDto> userInfoSearchDtos = new ArrayList<>(userInfoViews.size());

        for (UserInfoView sysEmailConfigTable : userInfoViews) {
            UserInfoSearchDto sysConfigSearchDto = transform(sysEmailConfigTable);
            userInfoSearchDtos.add(sysConfigSearchDto);
        }

        return new BaseResultWithPagerDto(pageDto, userInfoSearchDtos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLang(UserInfoUpdateLangEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstById(entity.getId());
        if (userInfoTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        if (entity.getLang() != null && !entity.getLang().equals(userInfoTable.getLang())) {
            userInfoTable.setLang(entity.getLang());
            userInfoRepository.save(userInfoTable);
        }
    }

    @Override
    public void updatePasswordSendEmail(UserUpdatePasswordSendEmailEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.getFirstByEmailNotNullAndEmail(entity.getEmail());

        if (userInfoTable == null || Strings.isNullOrEmpty(userInfoTable.getPassword())) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        SysEmailSendEntity sysEmailSendEntity = createUpdatePasswordSendEmailSysEmailEntity(entity, userInfoTable);


        redisService.save(sysEmailSendEntity.getMap().get(MapConstants.TOKEN), userInfoTable.getId(),
                Constants.EMAIL_TOKEN_TIME * 60 * 1000);

        mqSendService.send(Constants.ACTIVEMQ_JMS_URL_EMAIL, sysEmailSendEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(UserUpdateEmailPasswordEntity entity) throws ServiceException {

        Long id = redisService.getEntity(entity.getToken(), Long.class);
        if (id == null) {
            throw new ServiceException(Constants.EMAIL_EXPIRE);
        }

        UserInfoTable userInfoTable = userInfoRepository.findFirstById(id);

        if (userInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        /**
         * 填写修改时间和密码
         */
        userInfoTable.setPassword(entity.getPassword());
        userInfoTable.setModifyIp(entity.getModifyIp());
        userInfoTable.setModifyTime(entity.getModifyTime());
        userInfoTable.setModifyUser(userInfoTable.getModifyUser());

        userInfoRepository.save(userInfoTable);
        redisService.remove(entity.getToken());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(UserUpdateLoginPasswordEntity entity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstById(entity.getId());

        if (userInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        if (!entity.getOldPassword().equals(userInfoTable.getPassword())) {
            throw new ServiceException(Constants.PASSWORD_ERROR);
        }
        /**
         * 填写修改时间和密码
         */
        userInfoTable.setPassword(entity.getNewPassword());
        userInfoTable.setModifyIp(entity.getModifyIp());
        userInfoTable.setModifyTime(entity.getModifyTime());
        userInfoTable.setModifyUser(userInfoTable.getModifyUser());

        userInfoRepository.save(userInfoTable);
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    @Override
    public UserInfoSearchDto searchSingle(Long id) throws ServiceException {

        UserInfoView userInfoView = userInfoDao.getOne(id);
        if (userInfoView == null) {
            throw new DataNotFoundException(Constants.USER_NOT_EXIST_ERROR);
        }

        Long attachId = userInfoView.getAttachId();
        if (attachId != null && attachId > 0) {
            UserInfoTable attach = userInfoRepository.getOne(attachId);
            if (attach != null) {
                userInfoView.setAttachNo(attach.getIbNo());
            }
        }

        UserInfoSearchDto userInfoSearchDto = transform(userInfoView);

        return userInfoSearchDto;
    }

    @Override
    public UserInfoIbNoDto searchIbSingle(UserInfoIbSearchEntity entity) throws ServiceException {
        return null;
    }

    @Override
    public UserStaticDto getStaticData() throws Exception {
        UserStaticDto userStaticDto = new UserStaticDto();
        List<UserGroupTable> userGroupTables = userGroupRepository.findAll();

        if (userGroupTables != null && userGroupTables.size() > 0) {
            List<UserGroupDto> groups = new ArrayList<>(userGroupTables.size());
            userGroupTables.forEach(value -> {
                UserGroupDto userGroupDto = new UserGroupDto();
                BeanUtils.copyProperties(value, userGroupDto);
                groups.add(userGroupDto);
            });
            userStaticDto.setGroups(groups);
        }
        List<AgentLevelTable> agentLevelTables = agentLevelRepository.getAllByValid(1);

        if (agentLevelTables != null && agentLevelTables.size() > 0) {
            List<AgentLevelDto> levelDtos = new ArrayList<>(agentLevelTables.size());
            agentLevelTables.forEach(value -> {
                AgentLevelDto userGroupDto = new AgentLevelDto();
                BeanUtils.copyProperties(value, userGroupDto);
                levelDtos.add(userGroupDto);
            });
            userStaticDto.setAgentLevels(levelDtos);
        }
        return userStaticDto;
    }


    @Override
    public BaseResultDto<List<SalesInfoDropdownDto>> getSalesInfoDropdown() throws Exception {

        return getSalesInfoDropdown(null);
    }

    @Override
    public BaseResultDto<List<SalesInfoDropdownDto>> getSalesInfoDropdown(Long pId) throws Exception {
        String roleCode = "ROLE_SALE";

        List<UserInfoTable> tables = userInfoDao.findAllByRoleCode(roleCode, pId);
        List<SalesInfoDropdownDto> dtos = Lists.newArrayList();
        tables.forEach((table) -> {
            SalesInfoDropdownDto dto = new SalesInfoDropdownDto();
            dto.setEmail(table.getEmail());
            dto.setIbNo(table.getIbNo());
            dto.setId(table.getId());
            dto.setName(table.getName());
            dtos.add(dto);
        });

        return BaseResultDto.success(dtos);
    }

    @Override
    public BaseResultDto<List<SalesInfoDropdownDto>> getSalesLeaderInfoDropdown() throws ServiceException {


        List<UserInfoTable> tables = userInfoDao.getAllByLeader();
        List<SalesInfoDropdownDto> dtos = Lists.newArrayList();
        tables.forEach((table) -> {
            SalesInfoDropdownDto dto = new SalesInfoDropdownDto();
            dto.setEmail(table.getEmail());
            dto.setIbNo(table.getIbNo());
            dto.setId(table.getId());
            dto.setName(table.getName());
            dtos.add(dto);
        });

        return BaseResultDto.success(dtos);
    }

    @Override
    public String getStampByPId(Long pid) {

        UserInfoTable superIb = userInfoRepository.findOne(pid);
        List<UserInfoTable> tables = userInfoRepository.findAllByPid(pid);
        String nextNo = getNextNo(superIb.getStamp(), pid, tables);

        return nextNo;
    }

    /**
     * 获取同层级stamp
     *
     * @param parentNo 上级stamp
     * @param pid      上级ID
     * @param users    用户列表
     * @return
     */
    private String getNextNo(String parentNo, long pid,
                             List<UserInfoTable> users) {
        String maxNo = parentNo + "00";
        if (pid != 0) {
            for (UserInfoTable agent : users) {
                if (agent.getPid() == pid) {
                    if (StampUtil.compareStamp(maxNo, agent.getStamp() == null ? "0" : agent.getStamp())) {
                        maxNo = agent.getStamp();
                    }
                }
            }
        }

        return StampUtil.getStamp(maxNo);
    }


    /**
     * 验证用户名是否已存在
     *
     * @param username
     * @throws ServiceException
     */
    private void existByUsername(String username) throws ServiceException {
        boolean existByUsername = userInfoRepository.existsByUsername(username);
        if (existByUsername) {
            throw new ServiceException(Constants.USERNAME_IS_EXIST_ERROR);
        }
    }

    /**
     * 验证邮箱是否已存在
     *
     * @param email
     * @throws ServiceException
     */
    private void existByEmail(String email) throws ServiceException {
        boolean existByEmail = userInfoRepository.existsByEmail(email);
        if (existByEmail) {
            throw new ServiceException(Constants.EMAIL_IS_EXIST_ERROR);
        }
    }

    /**
     * 构建修改密码发送邮件实体
     *
     * @param entity
     * @param userInfoTable
     * @return
     */
    private SysEmailSendEntity createUpdatePasswordSendEmailSysEmailEntity(UserUpdatePasswordSendEmailEntity entity,
                                                                           UserInfoTable userInfoTable) {
        SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();
        String token =
                AESUtil.encrypt(entity.getEmail() + Constants.LOGIN_LINK + UUIDUtil.getUUID() + Constants.LOGIN_LINK + userInfoTable.getId());
        Date time = DateUtil.operationMinute(new Date(), Constants.EMAIL_TOKEN_TIME);
        Map<String, String> map = new HashMap<>(3);
        map.put(MapConstants.TOKEN, token);
        map.put(MapConstants.EXPIRE_TIME, DateUtil.formatTime(time));
        map.put(MapConstants.DATE_TIME, DateUtil.formatTime());

        sysEmailSendEntity.setAddIp(entity.getIp());
        sysEmailSendEntity.setAddTime(entity.getTime());
        sysEmailSendEntity.setAddUser(userInfoTable.getAddUser());
        sysEmailSendEntity.setUsers(entity.getEmail());
        sysEmailSendEntity.setEmailSendEnum(EmailSendEnum.FORGET_PASSWORD);
        if (CountryUtil.isCN(userInfoTable.getLang())) {
            sysEmailSendEntity.setTemplateName(SystemEmailCodeConstants.USER_UPDATE_PASSWORD_SEND_CN);
        } else {
            sysEmailSendEntity.setTemplateName(SystemEmailCodeConstants.USER_UPDATE_PASSWORD_SEND_EN);
        }
        sysEmailSendEntity.setMap(map);

        return sysEmailSendEntity;
    }

    @Autowired
    private TenantService tenantService;

    private InfoEntity transform(UserInfoTable userInfoTable, BaseLoginEntity entity, UserRoleDto userRoleDto,
                                 UserDepartmentSearchDto userDepartmentSearchDto, UserGroupTable userGroupTable) {

        InfoEntity infoEntity = new InfoEntity();
        IbInfoEntity userInfoEntity = new IbInfoEntity();
        if(!StringUtils.isEmpty(userInfoTable.getMerchantId())){
            TenantRespEntity single = tenantService.findSingle(userInfoTable.getMerchantId().longValue());
            if(!StringUtils.isEmpty(single)){
                userInfoEntity.setMerchantName(single.getMerchantName());
            }
        }
        BeanUtils.copyProperties(userInfoTable, userInfoEntity);

        if (!Strings.isNullOrEmpty(userInfoTable.getExcludeShowLoginTypes())) {
            userInfoEntity.setExcludeShowLoginTypes(Arrays.asList(userInfoTable.getExcludeShowLoginTypes().split(",")));
        }
        if (userRoleDto != null) {
            userInfoEntity.setRoleName(userRoleDto.getName());
            userInfoEntity.setRoteCode(userRoleDto.getCode());
        } else {
            userInfoEntity.setRoleName(ManagerConstant.ROLE_CODE_SYSTEM);
            userInfoEntity.setRoteCode(ManagerConstant.ROLE_CODE_SYSTEM);
        }
        if (userDepartmentSearchDto != null) {
            userInfoEntity.setDepartmentId(userDepartmentSearchDto.getId());
            userInfoEntity.setDepartmentName(userDepartmentSearchDto.getName());
        }

        if (userGroupTable != null) {
            userInfoEntity.setGroupEnName(userGroupTable.getEnName());
            userInfoEntity.setGroupName(userGroupTable.getName());
        }

        infoEntity.setIbInfo(userInfoEntity);
        infoEntity.setId(userInfoTable.getId());
        infoEntity.setThisAddress(entity.getAddress());
        infoEntity.setThisIp(entity.getIp());
        infoEntity.setThisTime(entity.getTime());
        infoEntity.setValid(userInfoTable.getValid() == null ? 0 : userInfoTable.getValid());
        infoEntity.setVerified(userInfoTable.getVerified() == null ? 0 : userInfoTable.getVerified());
        infoEntity.setSecretKey(userInfoTable.getSecretKey());

        PrefixEnum prefixEnum = getPrefixEnum(userInfoEntity.getRoteCode());
        infoEntity.setPrefix(prefixEnum);

        return infoEntity;
    }

//    private InfoEntity transform(UserInfoTable userInfoTable, UserAttachLoginEntity entity, UserRoleDto userRoleDto,
//                                 UserDepartmentSearchDto userDepartmentSearchDto, UserGroupTable userGroupTable) {
//
//        InfoEntity infoEntity = new InfoEntity();
//        IbInfoEntity userInfoEntity = new IbInfoEntity();
//
//        BeanUtils.copyProperties(userInfoTable, userInfoEntity);
//
//        if (!Strings.isNullOrEmpty(userInfoTable.getExcludeShowLoginTypes())) {
//            userInfoEntity.setExcludeShowLoginTypes(Arrays.asList(userInfoTable.getExcludeShowLoginTypes().split(",
//            ")));
//        }
//        if (userRoleDto != null) {
//            userInfoEntity.setRoleName(userRoleDto.getName());
//            userInfoEntity.setRoteCode(userRoleDto.getCode());
//        } else {
//            userInfoEntity.setRoleName(ManagerConstant.ROLE_CODE_SYSTEM);
//            userInfoEntity.setRoteCode(ManagerConstant.ROLE_CODE_SYSTEM);
//        }
//        if (userDepartmentSearchDto != null) {
//            userInfoEntity.setDepartmentId(userDepartmentSearchDto.getId());
//            userInfoEntity.setDepartmentName(userDepartmentSearchDto.getName());
//        }
//
//        if (userGroupTable != null) {
//            userInfoEntity.setGroupEnName(userGroupTable.getEnName());
//            userInfoEntity.setGroupName(userGroupTable.getName());
//        }
//
//        infoEntity.setIbInfo(userInfoEntity);
//        infoEntity.setId(userInfoTable.getId());
//        infoEntity.setThisAddress(entity.getAddress());
//        infoEntity.setThisIp(entity.getIp());
//        infoEntity.setThisTime(entity.getTime());
//        infoEntity.setValid(userInfoTable.getValid() == null ? 0 : userInfoTable.getValid());
//        infoEntity.setVerified(userInfoTable.getVerified() == null ? 0 : userInfoTable.getVerified());
//        infoEntity.setSecretKey(userInfoTable.getSecretKey());
//
//        PrefixEnum prefixEnum = getPrefixEnum(userInfoEntity.getRoteCode());
//        infoEntity.setPrefix(prefixEnum);
//
//        return infoEntity;
//    }


    /**
     * 转化(list转化为dtos)
     *
     * @param userInfoViews
     * @return
     */
    private List<UserInfoSearchDto> transform(List<UserInfoView> userInfoViews) {

        if (userInfoViews == null || userInfoViews.size() <= 0) {
            return null;
        }

        List<UserInfoSearchDto> transform = new ArrayList<>(userInfoViews.size());
        userInfoViews.forEach(value -> transform.add(transform(value)));

        return transform;
    }

    /**
     * 转化为dto
     *
     * @param userInfoView
     * @return
     */
    private UserInfoSearchDto transform(UserInfoView userInfoView) {

        UserInfoSearchDto userInfoSearchDto = new UserInfoSearchDto();

        BeanUtils.copyProperties(userInfoView, userInfoSearchDto);

        if (Strings.isNullOrEmpty(userInfoView.getSecretKey())) {
            userInfoSearchDto.setSecretKey(0);
        } else {
            userInfoSearchDto.setSecretKey(1);
        }
        if (!Strings.isNullOrEmpty(userInfoView.getExcludeShowLoginTypes())) {
            userInfoSearchDto.setExcludeShowLoginTypes(Arrays.asList(userInfoView.getExcludeShowLoginTypes().split(","
            )));
        }
        if (userInfoSearchDto.getEntryStatus() == null) {
            userInfoSearchDto.setEntryStatus(1);
        }
        return userInfoSearchDto;
    }

    private void limitIp(String ip, UserInfoTable userInfoTable) throws ServiceException {
        if (userInfoTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        if (userInfoTable.getIpLimit() == null || userInfoTable.getIpLimit().equals(0)) {
            return;
        }
        /**
         * 如果ip限制开启 则进行ip校验 如果记录上的ip限制地址不为空
         */
        if (!Strings.isNullOrEmpty(userInfoTable.getLimitIp())) {
            /**
             * 记录ip限制校验
             */
            if (!userInfoTable.getIpLimit().equals(ip)) {
                throw ServiceException.exception(Constants.RESTRICTED_LOGIN);
            }
        } else {
            boolean validateResult = sysIpLimitService.validatedIpExist(ip);
            if (!validateResult) {
                throw ServiceException.exception(Constants.RESTRICTED_LOGIN);
            }
        }
    }

    @Override
    public PrefixEnum getPrefixEnum(Long roleId) throws ServiceException {
        UserRoleDto userRoleDto;

        userRoleDto = userRoleService.getRoleInfo(roleId);
        if (userRoleDto == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        return getPrefixEnum(userRoleDto.getCode());
    }

    @Override
    public boolean existsByAreaId(Long areaId) throws Exception {

        Integer result = userInfoDao.existsByAreaId(areaId);

        return result == null || result == 0 ? false : true;
    }

    @Override
    public UserInfoTable getDataById(Long id) throws ServiceException {
        return userInfoRepository.findOne(id);
    }

    @Override
    public List<UserInfoTable> getAllByStamp(String stamp) throws ServiceException {
        return userInfoDao.findAllSalesAndSelfByStamp(stamp);
    }

    @Override
    public String getIdStamp(Long id, Long pid) {
        UserInfoTable superIb = userInfoRepository.findOne(pid);
        return StampUtil.formatIdStamp(id, superIb.getIdStamp());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initIdStamp() throws Exception {
        List<UserInfoTable> tables = userInfoRepository.findAll();
        for (UserInfoTable table : tables) {
            if ("01".equals(table.getIdStamp())) {
                recurseIdStamp(table, tables);
            }
        }

        List<List<UserInfoTable>> lists = ListSplitUtil.split(tables);
        for (List<UserInfoTable> list : lists) {
            userInfoDao.batchUpdateIdStamp(list);
        }

    }

    @Override
    public Map<String, Long> mapIdByIbNo(List<String> ibNos) throws ServiceException {
        Map<String, Long> map = Maps.newHashMap();
        List<UserInfoTable> tables = userInfoDao.findAllByIbNoIn(ibNos);
        for (UserInfoTable table : tables) {
            map.put(table.getIbNo(), table.getId());
        }


        return map;
    }

    @Override
    public BaseResultWithPagerDto getEntryUserList(UserInfoEntrySearchEntity entity) throws ServiceException {
        Integer count = userInfoDao.getEntryUserCount(entity);
        PageDto pageDto = PageDto.format(entity, count);
        if (count == null || count <= 0) {
            return ResultWithPagerDto.success(pageDto);
        }
        List<UserInfoView> userEntryViews = userInfoDao.getEntryUserList(entity);

        if (userEntryViews == null || userEntryViews.size() <= 0) {
            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        List<UserEntryInfoSearchDto> dtos = new ArrayList<>(userEntryViews.size());

        for (UserInfoView userInfoView : userEntryViews) {
            UserEntryInfoSearchDto dto = new UserEntryInfoSearchDto();
            BeanUtils.copyProperties(userInfoView, dto);
            dtos.add(dto);
        }

        return new BaseResultWithPagerDto(pageDto, dtos);
    }

    @Override
    public List<UserEntryInfoSearchDto> getUserList(UserInfoListEntity entity) throws ServiceException {
        List<UserInfoView> userEntryViews = userInfoDao.getUserList(entity);

        List<UserEntryInfoSearchDto> dtos = new ArrayList<>(userEntryViews.size());
        for (UserInfoView userInfoView : userEntryViews) {
            UserEntryInfoSearchDto dto = new UserEntryInfoSearchDto();
            BeanUtils.copyProperties(userInfoView, dto);
            dtos.add(dto);
        }

        return dtos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String resetPassword(UserResetPasswordEntity entity) throws Exception {
        UserInfoTable table = userInfoRepository.findFirstById(entity.getId());
        if (Strings.isNullOrEmpty(entity.getPassword())) {
            entity.setPassword(GetRandom.getRandomPasswordString());
        }

        SysConfigTable gogleConfigTable = sysConfigService.getByCode(ConfigConstants.GOOGLE_USER_ADMIN_API_PROPERTY);
        if (gogleConfigTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }

        if (1 == entity.getUpdateType() || 3 == entity.getUpdateType()) {
            table.setPassword(MD5Util.getMD5(entity.getPassword()));
            userInfoRepository.save(table);
        }
        if (2 == entity.getUpdateType() || 3 == entity.getUpdateType()) {
            GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(),
                    GooleUserAdminApiProperty.class);
            String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(),
                    property.getClientEmail(), property.getPrivateKey());

            if (GoogleAdminAPIHttp.getUser(accessToken, table.getEmail()) == null) {
                throw ServiceException.exception("GoogleEmail is not used");
            }

            Integer resposeCode = GoogleAdminAPIHttp.resetUserPassword(accessToken, table.getEmail(),
                    entity.getPassword());
            if (Constants.SUCCESS_CODE != resposeCode) {
                throw ServiceException.exception("invalid password,reset GoogleEmail password is error");
            }
        }

        return entity.getPassword();
    }

    @Override
    public UserInfoSalesDto getSalesInfo(UserInfoSalesSearchEntity entity) {
        UserInfoSalesDto dto = new UserInfoSalesDto();

        UserInfoTable salesTable = userInfoRepository.findFirstByIbNo(entity.getSalesNo());
        UserInfoIbNoDto sales = new UserInfoIbNoDto();
        BeanUtils.copyProperties(salesTable, sales);
        dto.setSales(sales);

        if (null != salesTable.getLeaderId()) {
            UserInfoTable salesCaptainTable = userInfoRepository.getFirstById(salesTable.getLeaderId());
            UserInfoIbNoDto salesCaptain = new UserInfoIbNoDto();
            BeanUtils.copyProperties(salesCaptainTable, salesCaptain);
            dto.setSalesCaptain(salesCaptain);
        }

        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExcludeShowLoginType(UserInfoUpdateExcludeShowLoginTypeEntity entity) throws Exception {
        UserInfoTable userInfoTable = userInfoRepository.findFirstById(entity.getId());
        if (userInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        BeanUtils.copyProperties(entity, userInfoTable);
        if (entity.getExcludeShowLoginTypes() != null && entity.getExcludeShowLoginTypes().size() > 0) {
            userInfoTable.setExcludeShowLoginTypes(String.join(",", entity.getExcludeShowLoginTypes()));
        } else {
            userInfoTable.setExcludeShowLoginTypes(null);
        }
        userInfoRepository.save(userInfoTable);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<UserAttachInfoDto> getUserAttachInfo(InfoEntity infoEntity) throws ServiceException {

        UserInfoTable userInfoTable = userInfoRepository.findFirstById(infoEntity.getIbInfo().getAttachId());
        if (userInfoTable == null) {
            return Collections.emptyList();
        } else {
            List<UserAttachInfoDto> dtos = new ArrayList<>();
            UserAttachInfoDto loginUser = new UserAttachInfoDto();
            loginUser.setId(infoEntity.getIbInfo().getId());
            loginUser.setName(infoEntity.getIbInfo().getName());
            dtos.add(loginUser);
            UserAttachInfoDto userAttachInfoDto = new UserAttachInfoDto();
            userAttachInfoDto.setId(userInfoTable.getId());
            userAttachInfoDto.setName(userInfoTable.getName());
            dtos.add(userAttachInfoDto);
            return dtos;
        }

    }

    @JmsListener(destination = Constants.SALES_ENTRY_ACCOUNT_APPROVE)
    @Transactional(rollbackFor = Exception.class)
    public void salesPerformanceStatistics(String content) throws Exception {
        log.info(String.format("SALES_ENTRY_ACCOUNT_APPROVE,content:%s", content));
        AccountApplyTable table = JSON.parseObject(content, AccountApplyTable.class);
        if (table == null) {
            log.error("SALES_ENTRY_ACCOUNT_APPROVE,table is null");
            return;
        }
        if (!Constants.MANAGER_COMPLETED_STATUS.equals(table.getAccountStatus())) {
            log.error("SALES_ENTRY_ACCOUNT_APPROVE,accountStatus is not MANAGER_COMPLETED_STATUS");
            return;
        }

        if (!Strings.isNullOrEmpty(table.getNote())) {
            String[] userstr = table.getNote().split(":");
            if (userstr.length == 2) {
                UserInfoTable user = userInfoRepository.getFirstById(Long.valueOf(userstr[1]));

                CustomLoginTable login = customLoginRepository.getCustomLoginByLoginAndPlatform(table.getLogin(),
                        table.getPlatform());
                if (user == null) {
                    log.error("SALES_ENTRY_ACCOUNT_APPROVE,user is null");
                    return;
                }
                if (login == null) {
                    log.error("SALES_ENTRY_ACCOUNT_APPROVE,login is null");
                    return;
                }
                login.setValid(0);
                login.setActivation(1);
                login.setLoginStatus(Constants.MANAGER_PENDING_STATUS);
                login.setCloseFunctions("1,3,4,5,6,7,9");
                customLoginRepository.save(login);

                user.setSalaryLogin(table.getLogin());
                user.setSalaryPlatform(table.getPlatform());
                userInfoRepository.save(user);

                CustomLoginDeleteExcludeAddEntity excludeAddEntity = new CustomLoginDeleteExcludeAddEntity();
                excludeAddEntity.setLogin(user.getSalaryLogin());
                excludeAddEntity.setPlatform(user.getSalaryPlatform());
                customLoginDeleteExcludeService.add(excludeAddEntity);

                sysRemitExcludeCidRepository.deleteByUserIdAndLoginIsNotNull(user.getId());
                SysRemitExcludeCidTable loginCidTable = new SysRemitExcludeCidTable();
                loginCidTable.setUserId(user.getId());
                loginCidTable.setCId(user.getCId());
                loginCidTable.setLogin(user.getSalaryLogin());
                loginCidTable.setPlatform(user.getSalaryPlatform());
                loginCidTable.setAddTime(new Date());
                sysRemitExcludeCidRepository.save(loginCidTable);
            }
        }

    }

    private void recurseIdStamp(UserInfoTable pUser, List<UserInfoTable> tables) {
        for (UserInfoTable table : tables) {
            if (pUser.getId().equals(table.getPid()) && !"01".equals(table.getIdStamp())) {
                table.setIdStamp(StampUtil.formatIdStamp(table.getId(), pUser.getIdStamp()));
                recurseIdStamp(table, tables);
            }
        }
    }

    private PrefixEnum getPrefixEnum(String code) {
        PrefixEnum prefixEnum;
        switch (code) {
            case ManagerConstant.ROLE_CODE_SYSTEM:
                prefixEnum = PrefixEnum.PREFIX_SYSTEM;
                break;
            case ManagerConstant.ROLE_CODE_SALE:
                prefixEnum = PrefixEnum.PREFIX_SALE;
                break;
            case ManagerConstant.ROLE_CODE_ADMIN:
                prefixEnum = PrefixEnum.PREFIX_ADMIN;
                break;
            case ManagerConstant.ROLE_CODE_FINANCE:
                prefixEnum = PrefixEnum.PREFIX_FINANCE;
                break;
            case ManagerConstant.ROLE_CODE_MARKET:
                prefixEnum = PrefixEnum.PREFIX_MARKET;
                break;
            case ManagerConstant.ROLE_CODE_LEGAL_AFFAIRS:
                prefixEnum = PrefixEnum.PREFIX_LEGAL_AFFAIRS;
                break;
            case ManagerConstant.ROLE_CODE_USER:
                prefixEnum = PrefixEnum.PREFIX_USER;
            default:
                prefixEnum = PrefixEnum.PREFIX_USER;
                break;
        }
        return prefixEnum;
    }

    private UserInfoTable findById(Long id) throws ServiceException {
        UserInfoTable userInfoTable = userInfoRepository.findFirstById(id);

        if (userInfoTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return userInfoTable;
    }

    private void validCode(UserLoginEntity entity, UserInfoTable userInfoTable) throws ServiceException {
        if (googleVerified) {
            if (userInfoTable.getVerified() != null && userInfoTable.getVerified().equals(1)) {
                loginValidateGoogleAuthenticatorCode(userInfoTable, entity.getGaCode());
            }

        } else {
            if (!Strings.isNullOrEmpty(entity.getEmailCode())) {
                loginValidateCode(userInfoTable.getEmail(), entity.getEmailCode());
            } else if (entity.getGaCode() != null) {
                loginValidateGoogleAuthenticatorCode(userInfoTable, entity.getGaCode());
            } else {
                throw ServiceException.exception(Constants.SYSTEM_ERROR);
            }
        }
    }
}
