package cn.ey.biz.module.system.service.engagement.code;

import cn.ey.biz.common.pojo.PageResult;
import cn.ey.biz.module.system.controller.engagement.code.vo.EngagementCodeRuleEntityVO;
import cn.ey.biz.module.system.controller.engagement.code.vo.EngagementCodeRuleRecordRespVO;
import cn.ey.biz.module.system.controller.engagement.code.vo.EngagementCodeRuleReq;
import cn.ey.biz.module.system.controller.engagement.code.vo.EngagementCodeRuleRespVO;
import cn.ey.biz.module.system.convert.engagement.code.EngagementCodeRuleConvert;
import cn.ey.biz.module.system.dal.dataobject.codeblock.CodeBlockLegalEntityDO;
import cn.ey.biz.module.system.dal.dataobject.engagement.code.SystemEngagementCodeRuleDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserDO;
import cn.ey.biz.module.system.dal.mapper.codeblock.CodeBlockLegalEntityMapper;
import cn.ey.biz.module.system.dal.mapper.engagement.code.SystemEngagementCodeRuleMapper;
import cn.ey.biz.module.system.dal.redis.codeblock.CodeBlockRedisDAO;
import cn.ey.biz.module.system.service.user.AdminUserService;
import cn.ey.biz.module.system.util.engagement.DistinctListUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;
import static cn.ey.biz.module.system.enums.ErrorCodeConstants.*;

/**
 * Code规则 Service 实现类
 */
@Service
public class EngagementCodeRuleServiceImpl implements EngagementCodeRuleService {
    @Resource
    private SystemEngagementCodeRuleMapper codeRuleMapper;

    @Resource
    private AdminUserService adminUserService;

    @Resource
    private CodeBlockLegalEntityMapper codeBlockLegalEntityMapper;

    @Resource
    private CodeBlockRedisDAO codeBlockRedisDAO;


    private static final Comparator<SystemEngagementCodeRuleDO> COMPARATOR_ID = Comparator
            .comparing(SystemEngagementCodeRuleDO::getId);

    @Override
    public List<Long> createCodeRule(List<EngagementCodeRuleReq> list) {
        if (CollectionUtil.isEmpty(list)) {
            throw exception(CODE_RULE_PARAM_NOT_EMPTY);
        }
        if (list.size() > 500) {
            throw exception(CODE_RULE_PARAM_NOT_MORE_THAN);
        }
        List<SystemEngagementCodeRuleDO> doList = new ArrayList<>();
        for (EngagementCodeRuleReq engagementCodeRuleReq : list) {
            SystemEngagementCodeRuleDO codeRuleDO = new SystemEngagementCodeRuleDO();
            codeRuleDO.setEntityCode(StringUtils.isBlank(engagementCodeRuleReq.getLegalEntityCode()) ? "-" : engagementCodeRuleReq.getLegalEntityCode());
            codeRuleDO.setBuCode(StringUtils.isBlank(engagementCodeRuleReq.getBuCode()) ? "-" : engagementCodeRuleReq.getBuCode());
            codeRuleDO.setOuCode(StringUtils.isBlank(engagementCodeRuleReq.getOuCode()) ? "-" : engagementCodeRuleReq.getOuCode());
            codeRuleDO.setMuCode(StringUtils.isBlank(engagementCodeRuleReq.getMuCode()) ? "-" : engagementCodeRuleReq.getMuCode());
            codeRuleDO.setSmuCode(StringUtils.isBlank(engagementCodeRuleReq.getSmuCode()) ? "-" : engagementCodeRuleReq.getSmuCode());
            codeRuleDO.setSlCode(StringUtils.isBlank(engagementCodeRuleReq.getSlCode()) ? "-" : engagementCodeRuleReq.getSlCode());
            codeRuleDO.setSslCode(StringUtils.isBlank(engagementCodeRuleReq.getSslCode()) ? "-" : engagementCodeRuleReq.getSslCode());
            doList.add(codeRuleDO);
        }

        List<SystemEngagementCodeRuleDO> codeRuleDOS = DistinctListUtils.distinctList(doList,
                SystemEngagementCodeRuleDO::getEntityCode,
                SystemEngagementCodeRuleDO::getBuCode,
                SystemEngagementCodeRuleDO::getOuCode,
                SystemEngagementCodeRuleDO::getMuCode,
                SystemEngagementCodeRuleDO::getSmuCode,
                SystemEngagementCodeRuleDO::getSlCode,
                SystemEngagementCodeRuleDO::getSslCode);
        if (codeRuleDOS.size() != doList.size()) {
            throw exception(CODE_RULE_LIST_REPEAT);
        }
        //检验库中是否存在
        checkExistList(doList);
        //新增
        codeRuleMapper.insertBatch(doList);
        codeBlockRedisDAO.delete();
        return doList.stream().map(SystemEngagementCodeRuleDO::getId).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCodeRule(List<Long> ids) {
        for (Long id : ids) {
            EngagementCodeRuleRespVO ruleRespVO = codeRuleMapper.selectById(id);
            if (null == ruleRespVO) {
                throw exception(CODE_RULE_NOT_EXISTS);
            }
        }
        codeRuleMapper.deleteBatchByIds(ids);
        codeBlockRedisDAO.delete();
    }

    @Override
    public EngagementCodeRuleRespVO getCodeRule(Long id) {
        return codeRuleMapper.selectById(id);
    }

    @Override
    public PageResult<EngagementCodeRuleRespVO> getCodeRulePage(EngagementCodeRuleEntityVO reqVO) {
        PageResult<SystemEngagementCodeRuleDO> pageResult = codeRuleMapper.selectPage(reqVO);
        return EngagementCodeRuleConvert.INSTANCE.doConvertVo(pageResult);
    }

    @Override
    public List<SystemEngagementCodeRuleDO> getCodeRuleSimpleList() {
        QueryWrapper<SystemEngagementCodeRuleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", false);
        queryWrapper.last("limit 1000");
        List<SystemEngagementCodeRuleDO> list = codeRuleMapper.selectList(queryWrapper);
        list.sort(COMPARATOR_ID);
        return list;
    }

    @Override
    public EngagementCodeRuleRecordRespVO getOperationRecord() {
        CodeBlockLegalEntityDO codeBlockLegalEntityDO = codeBlockLegalEntityMapper.selectOneForMaxTime();
        EngagementCodeRuleRecordRespVO codeRuleRecordRespVO = new EngagementCodeRuleRecordRespVO();
        if (null != codeBlockLegalEntityDO) {
            codeRuleRecordRespVO.setUpdater(codeBlockLegalEntityDO.getUpdater());
            codeRuleRecordRespVO.setUpdateTime(codeBlockLegalEntityDO.getUpdateTime());
        }
        AdminUserDO user = adminUserService.getUser(Long.valueOf(codeRuleRecordRespVO.getUpdater()));
        codeRuleRecordRespVO.setUpdater(user.getUsername());
        return codeRuleRecordRespVO;
    }


    private void checkExistList(List<SystemEngagementCodeRuleDO> doList) {
        List<EngagementCodeRuleRespVO> list = new ArrayList<>();
        for (SystemEngagementCodeRuleDO codeRuleDO : doList) {
            codeRuleDO.setDeleted(false);
            codeRuleDO.setVersion(1);
            List<EngagementCodeRuleRespVO> existList = checkIsExist(codeRuleDO);
            if (CollectionUtil.isNotEmpty(existList)) {
                list.add(existList.get(0));
            }
        }
        if (CollectionUtil.isNotEmpty(list)) {
            throw exception(CODE_RULE_EXISTS);
        }
    }

    private List<EngagementCodeRuleRespVO> checkIsExist(SystemEngagementCodeRuleDO codeRuleDO) {
        // 校验Code规则是否已存在
        return codeRuleMapper.selectByParam(codeRuleDO);
    }
}
