package com.sundot.airport.exam.logic.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import com.github.pagehelper.PageInfo;
import com.sundot.airport.exam.common.BizExceptionEnum;
import com.sundot.airport.exam.common.CheckUtil;
import com.sundot.airport.exam.common.HttpResult;
import com.sundot.airport.exam.common.PageData;
import com.sundot.airport.exam.common.manager.ExamRecordManager;
import com.sundot.airport.exam.common.model.params.ExamRecPageParam;
import com.sundot.airport.exam.common.model.params.GetExamRecordParam;
import com.sundot.airport.exam.common.model.result.ExamAndTpResult;
import com.sundot.airport.exam.common.model.result.GetExamRecordResult;
import com.sundot.airport.exam.common.model.result.sub.ExamRecordQuestion;
import com.sundot.airport.exam.common.service.*;
import com.sundot.airport.exam.common.service.impl.ExamServiceImpl;
import com.sundot.airport.exam.domain.Exam;
import com.sundot.airport.exam.domain.ExamRec;
import com.sundot.airport.exam.domain.TestPaper;
import com.sundot.airport.exam.enums.CloudSchoolBizExceptionEnum;
import com.sundot.airport.exam.logic.manage.model.params.*;
import com.sundot.airport.exam.logic.manage.model.result.*;
import com.sundot.airport.exam.logic.manage.model.result.sub.ExamCertRatingResult;
import com.sundot.airport.exam.logic.manage.model.result.sub.ExamRecordDetailOptResult;
import com.sundot.airport.exam.logic.manage.model.result.sub.ExamRecordDetailQuesResult;
import com.sundot.airport.exam.logic.manage.service.ExamBizService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <b>功能名：</b>ExamBizServiceImpl<br>
 * <b>说明：</b> 考试管理表业务类 <br>
 * <b>著作权：</b> Copyright (C) 2021 HUIFANEDU  CORPORATION<br>
 * <b>修改履历：
 *
 * @author 2021-06-23 liangxiao
 */
@Service
public class ExamBizServiceImpl implements ExamBizService {

    private static final Logger log = LoggerFactory.getLogger(ExamServiceImpl.class);

    @Resource
    private ExamService examService;

    @Resource
    private TestPaperService testPaperService;
    @Resource
    private ExamRecService examRecService;
    @Resource
    private ExamRecordManager examRecordManager;

    @Override
    public HttpResult<ExamAddResult> add(ExamAddParam param) {
        log.info(String.format("ExamBizServiceImpl.add:新增考试:param=%s", param));

        //启用证书，进行字段为空校验
        enableCertCheck(param);
        // 考试对象
        Exam entity = new Exam();
        BeanUtils.copyProperties(param, entity);
        // 检查考试名称是否重复
        Optional<Exam> nameCheck = examService.byNameCheckExistsGet(entity.getExName());
        CheckUtil.boolCheck(nameCheck.isPresent(), CloudSchoolBizExceptionEnum.DUPLICATE_NAME);
        // 检查考试实体参数信息
        validateParam(entity);
        // 保存考试
        Optional<Exam> insertOpt = examService.insert(entity);
        // 新增检查
        CheckUtil.boolCheck(!insertOpt.isPresent(), BizExceptionEnum.OPERATION_INSERT_ERROR);

        log.info(String.format("ExamBizServiceImpl.add:新增考试保存结果:insertOpt=%s,param=%s", insertOpt.get(), param));
        // 评级列表，启用证书
        if (entity.getExEnableCert()) {
            // 检查证书评级列表并保存列表
            //saveCertList(entity, param.getCertRatingList());
        }

        // 封装结果
        ExamAddResult result = new ExamAddResult();
        result.setExId(entity.getExId());
        return HttpResult.success(result);
    }

    @Override
    public HttpResult<Boolean> delete(ExamDelParam param) {
        // 考试删除前需要检查考试是否关联产品课程，如果关联不允许删除
//        Integer prodCount = prodCourseService.byExIdFindCount(param.getExId());
//        CheckUtil.boolCheck(prodCount <= 0,CloudSchoolBizExceptionEnum.RELATE_PROD_ENABLE);

        // 调用删除接口
        boolean exam = examService.delete(param.getExId());
        // 根据考试去删除证书评级
//        boolean certs = certRatingService.byExIdsDeleteList(Collections.singletonList(param.getExId()));
//        log.info(String.format("ExamBizServiceImpl.delete:删除考试:exam=%b,certs=%b,param=%s", exam, certs, param.toString()));
        return HttpResult.success(exam);
    }

    @Override
    public HttpResult<Boolean> update(ExamUpdParam param) {
        log.info(String.format("ExamBizServiceImpl.update:更新考试:param=%s", param));
        // 考试对象
        Exam entity = new Exam();
        BeanUtils.copyProperties(param, entity);
        // 检查考试名称是否重复
        Optional<Exam> nameCheck = examService.byNameCheckExistsGet(entity.getExName());
        CheckUtil.boolCheck(nameCheck.map(i -> !i.getExId().equals(param.getExId())).orElse(false), CloudSchoolBizExceptionEnum.DUPLICATE_NAME);
        // 检查考试实体参数信息
        validateParam(entity);
        // 更新考试
        entity.setUpdateTime(new Date());
        examService.update(entity);

//        // 评级列表，启用证书
//        if (entity.getExEnableCert()) {
//            // 根据考试去删除旧的证书评级信息
//            certRatingService.byExIdsDeleteList(Collections.singletonList(param.getExId()));
//            // 检查证书评级列表并保存列表
//            saveCertList(entity, param.getCertRatingList());
//        } else {
            // 关闭证书时要删除对应的证书信息
            entity.setExCertTh(0);
            entity.setExCertName("");
            entity.setExCertBgImg("");
            entity.setExCertQrCode("");
            entity.setExCertShareRemark("");
            entity.setPiId("");
//            // 根据考试去删除证书评级配置列表
//            certRatingService.byExIdsDeleteList(Collections.singletonList(entity.getExId()));
//        }

        return HttpResult.success(examService.update(entity));
    }

    @Override
    public HttpResult<ExamGetResult> get(String exId) {
        log.info(String.format("ExamBizServiceImpl.get:考试详情:exId=%s", exId));
        // 考试信息
        Optional<ExamAndTpResult> entity = examService.joinDataGet(exId, true);
        CheckUtil.boolCheck(!entity.isPresent(), CloudSchoolBizExceptionEnum.EXAM_NOT_FOUND);

        // 根据考试业务id列表查询关联的证书评级信息并构建结果
//        List<ExamCertRatingResult> crResults = byExIdsFindAndBuildResult(Collections.singletonList(entity.get().getExId()))
//                .collect(Collectors.toList());

        // 封装结果
        ExamGetResult result = new ExamGetResult();
        BeanUtils.copyProperties(entity.get(), result);
       // result.setCertRatingList(crResults);
        return HttpResult.success(result);
    }

    @Override
    public HttpResult<PageData<ExamPageResult>> pageList(ExamPageParam param) {
        log.info(String.format("ExamBizServiceImpl.pageList:考试分页:param=%s", param));
        // 分页条件查询
        PageInfo<Exam> pageInfo = examService.pageList(param);

        // 选项查询结果，key是quId，value是对应的选项
        Map<String, List<ExamCertRatingResult>> listMap;
        // 判断结果是否是简单模式
      //  if (param.getEasy()) {
            listMap = new HashMap<>(1);
//        } else {
//            // 题干分页结果的业务id列表
//            List<String> exIds = pageInfo
//                    .getList()
//                    .stream()
//                    .map(Exam::getExId)
//                    .collect(Collectors.toList());
//
//            // 根据考试业务id列表查询关联的证书评级信息并构建结果，然后用试卷业务id进行分组
//            listMap = byExIdsFindAndBuildResult(exIds).collect(Collectors.groupingBy(ExamCertRatingResult::getExId));
//        }

        // 试卷业务id列表
        List<String> tpIds = pageInfo
                .getList()
                .stream()
                .map(Exam::getTpId)
                .collect(Collectors.toList());
        List<TestPaper> testPaperList = testPaperService.byTpIdsFindTestPaper(tpIds);
        Map<String, TestPaper> testPaperMap = testPaperList.stream().collect(Collectors.toMap(TestPaper::getTpId, testPaper -> testPaper));

        // 组装分页数据
        PageData<ExamPageResult> pageData = new PageData<>(pageInfo);
        pageData.setList(pageInfo
                .getList()
                .stream()
                .map(res -> new ExamPageResult() {
                    {
                        // 初始化结果
                        BeanUtils.copyProperties(res, this);
                        // 初始化证书评级列表
                        this.setCertRatingList(listMap.getOrDefault(res.getExId(), Collections.emptyList()));
                        // 试卷名称
                        this.setTpName(testPaperMap.getOrDefault(res.getTpId(), new TestPaper()).getTpName());
                        // 试卷题目数
                        this.setTpQuesNum(testPaperMap.getOrDefault(res.getTpId(), new TestPaper()).getTpQuesNum());
                        // 试卷总分
                        this.setTpTotalScore(testPaperMap.getOrDefault(res.getTpId(), new TestPaper()).getTpTotalScore());
                        // 试卷分类表业务主键
                        this.setTpcId(testPaperMap.getOrDefault(res.getTpId(), new TestPaper()).getTpcId());
                    }
                }).collect(Collectors.toList()));

        return HttpResult.success(pageData);
    }

    /**
     * <b>方法名: </b> validateParam <br>
     * <b>说明: </b> 检查考试实体参数信息 <br>
     *
     * @param entity com.sundot.airport.exam.domain.Exam 考试实体
     * @return void<br>
     * <b>修改履历: </b>
     * @author 2021/6/24 liangxiao
     */
    private void validateParam(Exam entity) {
        // 检查试卷业务id是否有效
        CheckUtil.boolCheck(!testPaperService.get(entity.getTpId()).isPresent(), CloudSchoolBizExceptionEnum.EXAM_NOT_FOUND);
    }

//    /**
//     * <b>方法名: </b> saveCertList <br>
//     * <b>说明: </b> 检查证书评级列表并保存列表 <br>
//     *
//     * @param entity         com.sundot.airport.exam.domain.Exam 考试实体类
//     * @param certRatingList java.util.List<com.sundot.airport.logic.manage.model.params.ExamCertRatingParam> 证书评级列表参数
//     * @return void<br>
//     * <b>修改履历: </b>
//     * @author 2021/6/24 liangxiao
//     */
//    private void saveCertList(Exam entity, List<ExamCertRatingParam> certRatingList) {
//        // 启用证书时证书评级不能为空
//        CheckUtil.boolCheck(certRatingList == null || certRatingList.isEmpty(), CloudSchoolBizExceptionEnum.CERT_EMPTY);
//        // 转换证书评级列表
//        List<CertRating> newCertRatingList = certRatingList
//                .stream()
//                .map(i -> new CertRating() {
//                    {
//                        BeanUtils.copyProperties(i, this);
//                        // 设置证书评级关联的考试业务id
//                        this.setExId(entity.getExId());
//                    }
//                }).collect(Collectors.toList());
//        // 保存评级列表
//        certRatingService.insertList(newCertRatingList);
//    }

//    /**
//     * <b>方法名: </b> byExIdsFindAndBuildResult <br>
//     * <b>说明: </b> 根据考试业务id列表查询关联的证书评级信息并构建结果 <br>
//     *
//     * @param exIds java.util.List<java.lang.String> 考试业务id列表
//     * @return java.util.stream.Stream<com.sundot.airport.logic.manage.model.result.ExamCertRatingResult><br>
//     * <b>修改履历: </b>
//     * @author 2021/6/23 liangxiao
//     */
//    private Stream<ExamCertRatingResult> byExIdsFindAndBuildResult(List<String> exIds) {
//        // 转换结果
//        return certRatingService.byExIdFindList(exIds)
//                .stream()
//                .map(i -> new ExamCertRatingResult() {
//                    {
//                        BeanUtils.copyProperties(i, this);
//                    }
//                });
//    }

    @Override
    public HttpResult<PageData<ExamRecordPageResult>> recordList(ExamRecordPageParam param) {
        ExamRecPageParam pageParam = new ExamRecPageParam();
        BeanUtil.copyProperties(param, pageParam);
        PageInfo<ExamRec> pageInfo = examRecService.pageList(pageParam);
        // 组装分页数据
        PageData<ExamRecordPageResult> pageData = new PageData<>(pageInfo);
        pageData.setList(pageInfo
                .getList()
                .stream()
                .map(res -> new ExamRecordPageResult() {
                    {
                        // 将查询结果转换为Result对象
                        BeanUtils.copyProperties(res, this);
                        Integer score = res.getErScore();
                        Integer certTh = res.getErExCertTh();
                        if (res.getErExEnableCert() && score != null && certTh != null && score >= certTh) {
                            this.setGetCert(true);
                        }
                    }
                })
                .collect(Collectors.toList()));
        return HttpResult.success(pageData);
    }

    @Override
    public HttpResult<ExamRecordDetailResult> recordDetail(String erId) {
        GetExamRecordParam commonParam = new GetExamRecordParam();
        commonParam.setErId(erId);
        // 查询完整的测试记录、题目、用户答案
        GetExamRecordResult commonRes = examRecordManager.getExamRecord(commonParam);
        ExamRecordDetailResult httpRes = new ExamRecordDetailResult();
        BeanUtil.copyProperties(commonRes, httpRes);

        if (commonRes.getErScore() != null && commonRes.getErExCertTh() != null && commonRes.getErScore() >= commonRes.getErExCertTh()) {
            // 用户得分 与 证书门槛都有效时  写入证书发放时间 即考试记录更新时间
            httpRes.setCertTime(DatePattern.NORM_DATE_FORMAT.format(commonRes.getUpdateTime()));
        }

        // 将common查询结果类转换为请求返回结果类
        List<ExamRecordQuestion> questionList = commonRes.getQuestion();
        httpRes.setQuestion(questionList.stream().map(ques -> new ExamRecordDetailQuesResult() {
            {
                BeanUtil.copyProperties(ques, this);
                this.setOption(ques.getOption().stream().map(opt -> new ExamRecordDetailOptResult() {
                    {
                        BeanUtil.copyProperties(opt, this);
                    }
                }).collect(Collectors.toList()));
                //  将选项中的回答正确情况提出至问题
                this.setEroCorrectStatus(examRecordManager.getCorrectStatusByOpts(ques.getOption()));
            }
        }).collect(Collectors.toList()));
        return HttpResult.success(httpRes);
    }

    /**
     * <b>方法名: </b> enableCertCheck <br>
     * <b>说明: 判断是否启用证书，如果启用，判断必填字段不为空</b> <br>
     *
     * @param param com.sundot.airport.logic.manage.model.params.ExamAddParam 试卷添加参数
     * @return void<br>
     * <b>修改履历: </b>
     * @author 2021/7/30 lity
     */
    private void enableCertCheck(ExamAddParam param) {
        if (param.getExEnableCert()) {
            CheckUtil.objIsNull(param.getExCertTh(), BizExceptionEnum.REQUEST_NULL);
            CheckUtil.strCheck(param.getExCertName(), BizExceptionEnum.REQUEST_NULL);
            CheckUtil.strCheck(param.getExCertBgImg(), BizExceptionEnum.REQUEST_NULL);
            CheckUtil.listEmpty(param.getCertRatingList(), BizExceptionEnum.REQUEST_NULL);
            CheckUtil.strCheck(param.getExCertShareRemark(), BizExceptionEnum.REQUEST_NULL);
        }
    }
}
