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

import cn.ey.biz.common.pojo.PageParam;
import cn.ey.biz.common.pojo.PageResult;
import cn.ey.biz.common.util.json.JsonUtils;
import cn.ey.biz.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.ey.biz.module.system.api.code.dto.CodeBlockingLevelDTO;
import cn.ey.biz.module.system.controller.admin.code.vo.CodeBlockingLevelVO;
import cn.ey.biz.module.system.controller.admin.code.vo.HistoryVO;
import cn.ey.biz.module.system.convert.code.CodeBlockingLevelConvert;
import cn.ey.biz.module.system.dal.dataobject.code.CodeBlockingLevelDO;
import cn.ey.biz.module.system.dal.dataobject.code.CodeBlockingLevelVarDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserDO;
import cn.ey.biz.module.system.dal.mapper.code.CodeBlockingLevelMapper;
import cn.ey.biz.module.system.dal.mapper.code.CodeBlockingLevelVarMapper;
import cn.ey.biz.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Validated
@Slf4j
public class CodeBlockingLevelServiceImpl implements CodeBlockingLevelService {

    @Resource
    private CodeBlockingLevelMapper codeBlockingLevelMapper;

    @Resource
    private CodeBlockingLevelVarMapper codeBlockingLevelVarMapper;

    @Resource
    private AdminUserService adminUserService;

    @Override
    @Transactional
    public Long submitBlockingLevel(CodeBlockingLevelVO codeBlockingLevelVO) {

        LambdaUpdateWrapper<CodeBlockingLevelVarDO> varWrapper = new LambdaUpdateWrapper<>();
        varWrapper.eq(CodeBlockingLevelVarDO::getActive, 1);
        varWrapper.set(CodeBlockingLevelVarDO::getActive, 0);
        codeBlockingLevelVarMapper.update(null, varWrapper);

        CodeBlockingLevelVarDO varDO = new CodeBlockingLevelVarDO();
        varDO.setActive(1);
        varDO.setExplanation(codeBlockingLevelVO.getExplanation());
        codeBlockingLevelVarMapper.insert(varDO);

        codeBlockingLevelVO.getRules().forEach(rule -> {
            CodeBlockingLevelDO doo = CodeBlockingLevelConvert.INSTANCE.rule2Do(rule);
            doo.setVerId(varDO.getId());
            codeBlockingLevelMapper.insert(doo);
        });

        return varDO.getId();
    }

    @Override
    public PageResult<HistoryVO> getHistory(PageParam pageParam) {
        PageResult<CodeBlockingLevelVarDO> pageDo = codeBlockingLevelVarMapper.selectPage(pageParam,
                new LambdaQueryWrapperX<CodeBlockingLevelVarDO>().orderByDesc(CodeBlockingLevelVarDO::getCreateTime));
        PageResult<HistoryVO> pageHistory = new PageResult<>();
        pageHistory.setList(pageDo.getList().stream().map(doo -> {
            HistoryVO vo = CodeBlockingLevelConvert.INSTANCE.do2History(doo);
            String updater = doo.getUpdater();
            AdminUserDO user = adminUserService.getUser(Long.valueOf(updater));
            if (user != null) {
                vo.setUpdateUser(user.getUsername());
            }
            return vo;
        }).collect(Collectors.toList()));
        pageHistory.setTotal(pageDo.getTotal());
        return pageHistory;
    }

    @Override
    public CodeBlockingLevelDTO getCodeBlockingLevel(Long ver) {
        LambdaQueryWrapper<CodeBlockingLevelVarDO> queryVer = new LambdaQueryWrapper<>();
        if (ver != null) {
            queryVer.eq(CodeBlockingLevelVarDO::getId, ver);
        } else {
            queryVer.eq(CodeBlockingLevelVarDO::getActive, 1);
        }

        CodeBlockingLevelVarDO varDO = codeBlockingLevelVarMapper.selectOne(queryVer);

        if (Objects.isNull(varDO)) {
            return null;
        }

        LambdaQueryWrapper<CodeBlockingLevelDO> queryDo = new LambdaQueryWrapper<>();
        queryDo.eq(CodeBlockingLevelDO::getVerId, varDO.getId());
        List<CodeBlockingLevelDO> dos = codeBlockingLevelMapper.selectList(queryDo);

        CodeBlockingLevelDTO dto = new CodeBlockingLevelDTO();
        List<CodeBlockingLevelDTO.Rule> rules = dos.stream().map(doo -> {
            CodeBlockingLevelDTO.Rule rule = new CodeBlockingLevelDTO.Rule();
            rule.setCountry(doo.getCountry());
            rule.setRegion(doo.getRegion());
            rule.setSl(doo.getSl());
            rule.setCondition(JsonUtils.parseArray(doo.getRules(), CodeBlockingLevelDTO.Condition.class));
            return rule;
        }).collect(Collectors.toList());

        dto.setRules(rules);
        dto.setExplanation(varDO.getExplanation());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        dto.setDate(sdf.format(varDO.getCreateTime()));
        AdminUserDO user = adminUserService.getUser(Long.valueOf(varDO.getUpdater()));
        if (user != null) {
            dto.setUpdater(user.getUsername());
        }
        return dto;
    }

    @Override
    public void revertHistory(Long ver) {
        LambdaUpdateWrapper<CodeBlockingLevelVarDO> deleteOld = new LambdaUpdateWrapper<>();
        deleteOld.eq(CodeBlockingLevelVarDO::getActive, 1);
        deleteOld.set(CodeBlockingLevelVarDO::getActive, 0);
        codeBlockingLevelVarMapper.update(null, deleteOld);

        LambdaUpdateWrapper<CodeBlockingLevelVarDO> addNew = new LambdaUpdateWrapper<>();
        addNew.eq(CodeBlockingLevelVarDO::getId, ver);
        addNew.set(CodeBlockingLevelVarDO::getActive, 1);
        codeBlockingLevelVarMapper.update(null, addNew);
    }
}
