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.CodeEpDTO;
import cn.ey.biz.module.system.controller.admin.code.vo.CodeEpVO;
import cn.ey.biz.module.system.controller.admin.code.vo.HistoryVO;
import cn.ey.biz.module.system.convert.code.CodeEpConvert;
import cn.ey.biz.module.system.dal.dataobject.code.CodeEpDO;
import cn.ey.biz.module.system.dal.dataobject.code.CodeEpVerDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserDO;
import cn.ey.biz.module.system.dal.mapper.code.CodeEpMapper;
import cn.ey.biz.module.system.dal.mapper.code.CodeEpVerMapper;
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.stream.Collectors;

@Service
@Validated
@Slf4j
public class CodeEpServiceImpl implements CodeEpService {

    @Resource
    private CodeEpVerMapper codeEpVerMapper;

    @Resource
    private CodeEpMapper codeEpMapper;

    @Resource
    private AdminUserService adminUserService;

    @Override
    @Transactional
    public Long submitEp(CodeEpVO codeEpVO) {

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

        CodeEpVerDO verDO = new CodeEpVerDO();
        verDO.setActive(1);
        verDO.setExplanation(codeEpVO.getExplanation());
        codeEpVerMapper.insert(verDO);

        codeEpVO.getRules().forEach(rule -> {
            CodeEpDO codeEpDO = CodeEpConvert.INSTANCE.rule2Do(rule);
            codeEpDO.setVerId(verDO.getId());
            codeEpMapper.insert(codeEpDO);
        });

        return verDO.getId();
    }

    @Override
    public PageResult<HistoryVO> getHistory(PageParam pageParam) {
        PageResult<CodeEpVerDO> pageDo = codeEpVerMapper.selectPage(pageParam,
                new LambdaQueryWrapperX<CodeEpVerDO>().orderByDesc(CodeEpVerDO::getCreateTime));
        PageResult<HistoryVO> pageHistory = new PageResult<>();
        pageHistory.setList(pageDo.getList().stream().map(doo -> {
            HistoryVO vo = CodeEpConvert.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 CodeEpDTO getCodeEpLevel(Long ver) {
        LambdaQueryWrapper<CodeEpVerDO> queryVer = new LambdaQueryWrapper<>();
        if (ver != null) {
            queryVer.eq(CodeEpVerDO::getId, ver);
        } else {
            queryVer.eq(CodeEpVerDO::getActive, 1);
        }
        CodeEpVerDO verDO = codeEpVerMapper.selectOne(queryVer);

        LambdaQueryWrapper<CodeEpDO> queryEp = new LambdaQueryWrapper<>();
        queryEp.eq(CodeEpDO::getVerId, verDO.getId());
        List<CodeEpDO> CodeEpDOs = codeEpMapper.selectList(queryEp);
        List<CodeEpDTO.Rule> rules = CodeEpDOs.stream()
                .map(CodeEpConvert.INSTANCE::do2Rule).collect(Collectors.toList());
        CodeEpDTO dto = new CodeEpDTO();
        dto.setRules(rules);
        dto.setExplanation(verDO.getExplanation());

//        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 CodeEpVO getCodeEpLevelForFront(Long ver) {
        LambdaQueryWrapper<CodeEpVerDO> queryVer = new LambdaQueryWrapper<>();
        if (ver != null) {
            queryVer.eq(CodeEpVerDO::getId, ver);
        } else {
            queryVer.eq(CodeEpVerDO::getActive, 1);
        }
        CodeEpVerDO verDO = codeEpVerMapper.selectOne(queryVer);

        LambdaQueryWrapper<CodeEpDO> queryEp = new LambdaQueryWrapper<>();
        queryEp.eq(CodeEpDO::getVerId, verDO.getId());
        List<CodeEpDO> CodeEpDOs = codeEpMapper.selectList(queryEp);
        List<CodeEpVO.Rule> rules = CodeEpDOs.stream()
                .map(CodeEpConvert.INSTANCE::do2RuleVO).collect(Collectors.toList());
        CodeEpVO vo = new CodeEpVO();
        vo.setRules(rules);
        vo.setExplanation(verDO.getExplanation());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        vo.setDate(sdf.format(verDO.getCreateTime()));
        AdminUserDO user = adminUserService.getUser(verDO.getUpdater() != null
                ? Long.parseLong(verDO.getUpdater()) : 0L);
        if (user != null) {
            vo.setUpdater(user.getUsername());
        }
        return vo;
    }

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

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