package com.zd.exam.service.convert;

import cn.hutool.json.JSONUtil;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.exam.domain.ElConvertRecord;
import com.zd.exam.domain.ElScoreRewardconfig;
import com.zd.exam.enums.ConvertType;
import com.zd.exam.mapper.ElConvertRecordMapper;
import com.zd.exam.mapper.ElCourseChapterMapper;
import com.zd.exam.mapper.ElPaperMapper;
import com.zd.exam.service.IElConvertRecordService;
import com.zd.exam.service.IElPointsRecordService;
import com.zd.exam.service.IElScoreRewardconfigService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
@EnableScheduling
public class ConvertTimingService {
    private static final Logger logger = LoggerFactory.getLogger(ConvertTimingService.class);
    @Autowired
    private IElConvertRecordService convertRecordService;
    @Autowired
    private ElConvertRecordMapper elConvertRecordMapper;
    @Autowired
    private IElScoreRewardconfigService scoreRewardconfigService;
    @Autowired
    private IElPointsRecordService pointsRecordService;
    @Autowired
    private ElCourseChapterMapper elCourseChapterMapper;
    @Autowired
    private ElPaperMapper elPaperMapper;

    /**
     * 奖励分兑换任务
     */
    @Scheduled(fixedRate=5 * 60 * 1000)
    @Transactional
    public void doConvert() {

        ElConvertRecord elConvertRecord = new ElConvertRecord();
        elConvertRecord.setStatus(0);
        List<ElConvertRecord> list = convertRecordService.selectElConvertRecordList(elConvertRecord);

        Map<Object, List<ElConvertRecord>> groupMap =  list.stream().filter(item-> item.getType() != null && item.getUserId() != null)
                .collect(Collectors.groupingBy(ElConvertRecord::getType));

        // 查询奖励分配置规则
        List<ElScoreRewardconfig> scoreRewardconfigs = scoreRewardconfigService.selectElScoreRewardconfigList(null);
        if(CollectionUtils.isEmpty(scoreRewardconfigs)){
            throw new ServiceException("未查询到奖励分配置规则");
        }

        for (Map.Entry<Object, List<ElConvertRecord>> m : groupMap.entrySet()) {
            list = m.getValue();

            for (ElConvertRecord convertRecord : list) {
                doObtainBonusPoints(scoreRewardconfigs.get(0), convertRecord);
            }

        }
    }

    public Long doConvertById(Long id){

        Long points = 0L;
        try {
            ElConvertRecord convertRecord = elConvertRecordMapper.selectElConvertRecordById(id);

            if(convertRecord != null){

                if(convertRecord.getStatus() == 1){
                    // 防止重复兑换
                    points = convertRecord.getConvertNum();
                }else {
                    // 查询奖励分配置规则
                    List<ElScoreRewardconfig> scoreRewardconfigs = scoreRewardconfigService.selectElScoreRewardconfigList(null);
                    if(CollectionUtils.isEmpty(scoreRewardconfigs)){
                        throw new ServiceException("未查询到奖励分配置规则");
                    }

                    points = doObtainBonusPoints(scoreRewardconfigs.get(0), convertRecord);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("doConvertById: error" + e.getMessage());
        }

        return points;
    }

    private Long doObtainBonusPoints(ElScoreRewardconfig scoreRewardconfig, ElConvertRecord convertRecord){
        Map<String,Object> obtainBonusPoints = new HashMap<>();
        String channelType = "", reason = "";
        Long deductPoints = 0L,legacyNum = 0L;
        boolean isLegacy = false;
        // 用户
        obtainBonusPoints.put("joinUserId", convertRecord.getUserId());
        // 渠道资源
        obtainBonusPoints.put("channelSource", convertRecord.getBusinessId());

        // 模拟练习每题获得奖励分值 乘法取余
        Long rpactiseRule = scoreRewardconfig.getExerciseScore();

        // 模拟考试 除法取余
        Long examRule = scoreRewardconfig.getMockExam();

        // 学习时长 除法取余
        Long learnRule = scoreRewardconfig.getStudyLen();

        // 暂时只处理 非遗留的换算
        if(convertRecord.getParentId() == null){
            // deductPoints 奖励分计算并 取余数值保留用作下次计算
            if(ConvertType.PRACTISE.equals(convertRecord.getType()) && rpactiseRule != null && rpactiseRule > 0){
                isLegacy = true;
                channelType = ConvertType.rewardType.PRACTISE.toString();
                deductPoints = convertRecord.getBusinessNum() * rpactiseRule;
                convertRecord.setUseNum(convertRecord.getBusinessNum());
                reason = "练习得分";

            }else if(ConvertType.EXAMPAPER.equals(convertRecord.getType()) && examRule != null && examRule > 0){
                isLegacy = true;
                channelType = ConvertType.rewardType.EXAMPAPER.toString();

                deductPoints = convertRecord.getBusinessNum()/examRule;
                legacyNum = convertRecord.getBusinessNum()%examRule;
                convertRecord.setUseNum(deductPoints * examRule);

                // 此ID 为试卷ID 需反查出考试名称
                String examTitle = Optional.ofNullable(elPaperMapper.selectExamTitleByPaperId(convertRecord.getBusinessId())).orElse("");

                reason = examTitle + "考试得分";
            }else if(ConvertType.LEARN.equals(convertRecord.getType()) && learnRule != null && learnRule > 0){
                isLegacy = true;
                channelType = ConvertType.rewardType.LEARN.toString();

                logger.error(JSONUtil.toJsonStr(convertRecord));
                // 学习时长秒转分钟

                deductPoints = (convertRecord.getBusinessNum()/60)/learnRule;
                convertRecord.setUseNum(deductPoints * 60 * learnRule);
                legacyNum = (convertRecord.getBusinessNum()/60)%learnRule;

                logger.error("deductPoints : " + deductPoints  + ",legacyNum :" + legacyNum);

                // 此ID 为学习记录ID 需要反查出资源名称
                String courseTitle = Optional.ofNullable(elCourseChapterMapper.selectCourseTitleByChapterId(convertRecord.getBusinessId())).orElse("");
                reason = courseTitle+ "学习得分";
            }else if(ConvertType.ASSESS.equals(convertRecord.getType()) && rpactiseRule != null && rpactiseRule > 0){
                isLegacy = true;
                channelType = ConvertType.rewardType.PRACTISE.toString();
                deductPoints = convertRecord.getBusinessNum() * rpactiseRule;
                convertRecord.setUseNum(convertRecord.getBusinessNum());
                // TODO 考核的课程章节
                reason = "考核得分";
            }

            // 渠道类型
            obtainBonusPoints.put("channelType", channelType);
            // 奖励的分数
            obtainBonusPoints.put("deductPoints", deductPoints);

            // 奖励的原因
            obtainBonusPoints.put("reason", reason);
            if(deductPoints > 0){
                // 兑换成功才保存
                if(pointsRecordService.obtainBonusPoints(obtainBonusPoints) == 200){
                    // 无论有没有设置兑换规则 都变更为已兑换，设置之前的数据不应该累计的设置之后
                    convertRecord.setStatus(1);
                    convertRecord.setConvertNum(deductPoints);

                    convertRecordService.updateElConvertRecord(convertRecord);

                    if(isLegacy && legacyNum > 0){
                        // TODO 如果有，则先遗留记录，欠缺 触发的实际换算，
                        ElConvertRecord convertLegacy = new ElConvertRecord();
                        convertLegacy.setType(convertRecord.getType());
                        // 此处业务ID 为父级ID
                        convertLegacy.setBusinessId(convertRecord.getBusinessId());
                        convertLegacy.setParentId(convertRecord.getId());
                        convertLegacy.setBusinessNum(legacyNum);
                        convertLegacy.setStatus(0);
                        convertLegacy.setUseNum(0L);
                        convertLegacy.setUserId(convertRecord.getUserId());

                        convertLegacy.setCreateBy(convertRecord.getCreateBy());
                        convertLegacy.setCreateTime(DateUtils.getNowDate());
                        convertLegacy.setDeptId(convertRecord.getDeptId());
                        convertLegacy.setDeptName(convertRecord.getDeptName());
                        elConvertRecordMapper.insertElConvertRecord(convertLegacy);
                    }
                }else {
                    logger.error("进行了积分兑换，但是没有兑换成功！");
                }
            }
        }
        return deductPoints;
    }
}
