package cn.ey.biz.module.system.service.delegation;

import cn.ey.biz.common.exception.util.ServiceExceptionUtil;
import cn.ey.biz.common.pojo.PageResult;
import cn.ey.biz.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.ey.biz.module.system.api.delegation.dto.UserDelegationDTO;
import cn.ey.biz.module.system.api.delegation.dto.UserDelegationReqDTO;
import cn.ey.biz.module.system.controller.admin.delegation.vo.UserDelegationPageReqVO;
import cn.ey.biz.module.system.controller.admin.delegation.vo.UserDelegationSaveReqVO;
import cn.ey.biz.module.system.convert.delegation.DelegationConvert;
import cn.ey.biz.module.system.dal.dataobject.delegation.UserDelegationDO;
import cn.ey.biz.module.system.dal.mapper.delegation.UserDelegationMapper;
import cn.ey.biz.module.system.enums.ErrorCodeConstants;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 代理人代理关系 Service 实现类
 * @author Jian.Yang
 * @date  2023-02-24
 */
@Service
public class UserDelegationServiceImpl extends ServiceImpl<UserDelegationMapper, UserDelegationDO> implements UserDelegationService {

    @Resource
    private UserDelegationMapper userDelegationMapper;

    @Override
    public PageResult<UserDelegationDO> getUserDelegationPage(UserDelegationPageReqVO reqVO) {
        return userDelegationMapper.selectPage(reqVO, new LambdaQueryWrapperX<UserDelegationDO>()
                .eq(StringUtils.isNotEmpty(reqVO.getAppId()), UserDelegationDO::getAppId, reqVO.getAppId())
                .eq(reqVO.getAgentUserInfo().getUserId() != null, UserDelegationDO::getAgentUserId, reqVO.getAgentUserInfo().getUserId())
                .likeIfPresent(UserDelegationDO::getAgentUserName, reqVO.getAgentUserInfo().getUserName())
                .likeIfPresent(UserDelegationDO::getAgentGpn, reqVO.getAgentUserInfo().getGpn())
                .likeIfPresent(UserDelegationDO::getAgentEmail, reqVO.getAgentUserInfo().getEmail())
                .orderByDesc(UserDelegationDO::getUserId));
    }

    @Override
    public void saveUserDelegationList(List<UserDelegationSaveReqVO> saveReqVO) {
        checkBizDuplicate(saveReqVO);
        List<UserDelegationDO> userDelegationEntities = DelegationConvert.INSTANCE.convertList2DO(saveReqVO);
        this.saveOrUpdateBatch(userDelegationEntities);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteUserDelegationList(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DELEGATION_ARGUMENTS_NOT_NULL);
        }
        userDelegationMapper.deleteBatchIds(ids);
    }

    private void checkBizDuplicate(List<UserDelegationSaveReqVO> saveReqVO) {
        if (CollUtil.isNotEmpty(saveReqVO)) {
            Map<String, Long> updateData = saveReqVO.stream().filter(reqItem -> reqItem.getId() != null)
                    .collect(Collectors.toMap(x -> String.join("-", x.getAppId(), String.valueOf(x.getAgentUserId()), String.valueOf(x.getUserId())), UserDelegationSaveReqVO::getUserId));
            // 判断新增数据相同业务主键数据是否已存在 agentUserId userId, appId
            List<UserDelegationDO> existsEntities = userDelegationMapper.getBizUnique(saveReqVO);
            if (CollUtil.isNotEmpty(existsEntities)) {
                StringBuilder sb = new StringBuilder();
                for (UserDelegationDO entity : existsEntities) {
                    String key = String.join("-", entity.getAppId(), String.valueOf(entity.getAgentUserId()), String.valueOf(entity.getUserId()));
                    boolean bl = (updateData.get(key) != null && ObjectUtil.notEqual(updateData.get(key), entity.getId()))
                            || updateData.get(key) == null;
                    if (bl) {
                        sb.append("代理人用户编码:").append(entity.getAgentUserId()).append("-")
                                .append("被代理人用户编码:").append(entity.getUserId()).append("关系");
                    }
                }
                if (CharSequenceUtil.isNotEmpty(sb.toString())) {
                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.DELEGATION_UNIT_DATA_DUPLICATE, sb.toString());
                }
            }
        }
    }

    @Override
    public List<UserDelegationDTO> getUserDelegation(String app, String gpn) {
        if (StringUtils.isEmpty(app) || StringUtils.isEmpty(gpn)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DELEGATION_ARGUMENTS_NOT_NULL);
        }
        UserDelegationReqDTO req = new UserDelegationReqDTO();
        req.setAppId(app).setAgentGpn(gpn);
        List<UserDelegationDO> userDelegationEntities = userDelegationMapper.selectList(getQueryWrapper(req));
        return DelegationConvert.INSTANCE.convertList2DTO(userDelegationEntities);
    }


    @Override
    public List<UserDelegationDO> listDelegation(UserDelegationReqDTO req) {
        return userDelegationMapper.selectList(getQueryWrapper(req));
    }

    private LambdaQueryWrapper<UserDelegationDO> getQueryWrapper(UserDelegationReqDTO req) {
        return new LambdaQueryWrapperX<UserDelegationDO>()
                .eqIfPresent(UserDelegationDO::getAppId, req.getAppId())
                .likeIfPresent(UserDelegationDO::getAgentGpn, req.getAgentGpn())
                .likeIfPresent(UserDelegationDO::getAgentUserName, req.getAgentUserName())
                .likeIfPresent(UserDelegationDO::getAgentEmail, req.getAgentEmail())
                .eqIfPresent(UserDelegationDO::getAgentUserId, req.getAgentUserId())
                .likeIfPresent(UserDelegationDO::getGpn, req.getGpn())
                .likeIfPresent(UserDelegationDO::getUserName, req.getUserName())
                .likeIfPresent(UserDelegationDO::getEmail, req.getEmail())
                .eqIfPresent(UserDelegationDO::getUserId, req.getUserId());
    }
}
