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.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.ey.biz.module.system.api.code.dto.CodeOtherDTO;
import cn.ey.biz.module.system.controller.admin.code.vo.CodeOtherVO;
import cn.ey.biz.module.system.controller.admin.code.vo.HistoryVO;
import cn.ey.biz.module.system.convert.code.CodeOtherConvert;
import cn.ey.biz.module.system.dal.dataobject.code.CodeOtherDO;
import cn.ey.biz.module.system.dal.dataobject.code.CodeOtherVerDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserDO;
import cn.ey.biz.module.system.dal.mapper.code.CodeOtherMapper;
import cn.ey.biz.module.system.dal.mapper.code.CodeOtherVerMapper;
import cn.ey.biz.module.system.service.user.AdminUserService;
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.stream.Collectors;

@Service
@Validated
@Slf4j
public class CodeOtherServiceImpl implements CodeOtherService {

    @Resource
    private CodeOtherVerMapper codeOtherVerMapper;

    @Resource
    private CodeOtherMapper CodeOtherMapper;

    @Resource
    private AdminUserService adminUserService;

    @Override
    @Transactional
    public Long submitOther(CodeOtherVO codeOtherVO) {

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

        CodeOtherVerDO varDO = new CodeOtherVerDO();
        varDO.setActive(1);
        varDO.setExplanation(codeOtherVO.getExplanation());
        codeOtherVerMapper.insert(varDO);

        codeOtherVO.getRules().forEach(rule -> {
            CodeOtherDO codeOtherDO = CodeOtherConvert.INSTANCE.rule2Do(rule);
            codeOtherDO.setVerId(varDO.getId());
            CodeOtherMapper.insert(codeOtherDO);
        });

        return varDO.getId();
    }

    @Override
    public PageResult<HistoryVO> getHistory(PageParam pageParam) {
        PageResult<CodeOtherVerDO> pageDo = codeOtherVerMapper.selectPage(pageParam,
                new LambdaQueryWrapperX<CodeOtherVerDO>().orderByDesc(CodeOtherVerDO::getCreateTime));
        PageResult<HistoryVO> pageHistory = new PageResult<>();
        pageHistory.setList(pageDo.getList().stream().map(doo -> {
            HistoryVO vo = CodeOtherConvert.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 CodeOtherDTO getCodeOther(Long ver) {
        LambdaUpdateWrapper<CodeOtherVerDO> queryVer = new LambdaUpdateWrapper<>();
        if (ver != null) {
            queryVer.eq(CodeOtherVerDO::getId, ver);
        } else {
            queryVer.eq(CodeOtherVerDO::getActive, 1);
        }

        CodeOtherVerDO verDo = codeOtherVerMapper.selectOne(queryVer);

        LambdaUpdateWrapper<CodeOtherDO> queryDo = new LambdaUpdateWrapper<>();
        queryDo.eq(CodeOtherDO::getVerId, verDo.getId());
        List<CodeOtherDO> dos = CodeOtherMapper.selectList(queryDo);
        List<CodeOtherDTO.Rule> rules = dos.stream()
                .map(CodeOtherConvert.INSTANCE::do2Rule).collect(Collectors.toList());

        CodeOtherDTO dto = new CodeOtherDTO();
        dto.setExplanation(verDo.getExplanation());
        dto.setRules(rules);

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

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

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