package jnpf.cultivate.controller.app.exam;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import jnpf.base.ActionResult;
import jnpf.base.vo.PageListVO;
import jnpf.cultivate.service.FtbCultivateExamService;
import jnpf.cultivate.service.FtbCultivateExamUserService;
import jnpf.model.cultivate.dto.statistics.CultivateUserExamCountDTO;
import jnpf.model.cultivate.po.exam.FtbCultivateExamUser;
import jnpf.model.cultivate.req.exam.*;
import jnpf.model.cultivate.resp.*;
import jnpf.model.enums.CourseEnums;
import jnpf.permission.entity.PositionEntity;
import jnpf.util.FtbUtil;
import jnpf.util.QuestionAnalysisUtil;
import jnpf.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * app考试模块
 *
 * @author xxxxx
 */
@Slf4j
@RestController
@RequestMapping("/app/exam")
public class ExamController {
    /**
     * 考试服务
     */
    @Resource
    private FtbCultivateExamService examService;

    /**
     * 考试用户服务
     */
    @Resource
    private FtbCultivateExamUserService examUserService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 开始考试界面，根据考试ID查询考试信息
     *
     * @param examId 考试id
     * @return
     */
    @GetMapping("/queryExamDetail/{examId}")
    public ActionResult<ExamAppVo> queryExamDetail(@PathVariable("examId") String examId) {
        ExamAppVo vo = examService.examInfo(examId);
        if (vo != null) {
//           查询这个考试已经完成的考试人数
            vo.setCompleteUserNum(examUserService.queryCompleteNumForExamId(examId));
        }
        return ActionResult.success(vo);
    }

    /**
     * app批阅考试查询考试信息（简单）
     *
     * @param userExamId 用户考试记录id
     * @return
     */
    @GetMapping("/queryUserExamSimpleMsg/{userExamId}")
    public ActionResult<UserExamDetailVo> queryUserExamSimpleMsg(@PathVariable("userExamId") String userExamId) {
        return ActionResult.success(examUserService.queryUserExamSimpleMsg(userExamId));
    }

    /**
     * 查询用户考试记录基本信息
     *
     * @param userExamId
     * @return
     */
    @GetMapping("/queryBaseUserExamInfo/{userExamId}")
    public ActionResult<UserExamDetailVo> queryBaseUserExamInfo(@PathVariable("userExamId") String userExamId) {
        return ActionResult.success(examUserService.queryBaseUserExamInfo(userExamId));
    }


    /**
     * 开始考试-查询考试的所有题目信息
     *
     * @param userExamId 用户考试id
     * @param req
     * @return
     */
    @GetMapping("/queryQuestionListForExam/{userExamId}")
    public ActionResult<PaperQuestionVo> queryQuestionListForExam(@PathVariable("userExamId") String userExamId, @Valid AppQueryExamQuestionReq req) {
        return ActionResult.success( QuestionAnalysisUtil.convertPaperQuestionVo(examService.queryExamQuestionListByUserExamId(userExamId), Collections.emptyList()));
    }


    /**
     * 重新开始考试
     *
     * @param userExamId 用户考试id
     * @return
     */
    @GetMapping("/reStartExam/{userExamId}")
    public ActionResult<UserExamDetailVo> reStartExam(@PathVariable("userExamId") String userExamId) {
        //如果是随机考试 还要随机抽题
        return ActionResult.success(BeanUtil.copyProperties(examUserService.reStartExam(userExamId), UserExamDetailVo.class));
    }

    /**
     * 提交试卷
     *
     * @param userExamId 用户考试ID
     * @param req
     * @return
     */
    @PostMapping("/sub-exam/{userExamId}")
    public ActionResult<SubExamVo> subExam(@PathVariable("userExamId") String userExamId, @RequestBody @Valid SubExamQuestionReq req) {

        FtbCultivateExamUser examUser = examUserService.getById(userExamId);

        if (null == examUser || examUser.getEnabledMark() == 0) {
            return ActionResult.fail(1000, "考试记录已经删除");
        }
        String lockKey = "subExam" + userExamId;
        if (redisTemplate.opsForValue().setIfAbsent(lockKey, UUID.randomUUID().toString(), 10, TimeUnit.SECONDS)) {
            try {
                SubExamVo subExamVo = examUserService.subExam(userExamId, req);
                return ActionResult.success(subExamVo);
            } catch (Exception e) {
                throw e;
            } finally {
                redisTemplate.delete(lockKey);
            }
        } else {
            throw new RuntimeException("考试提交中,请不要重复提交");
        }
    }


    /**
     * 视为作弊提交试卷
     *
     * @param cheatType  作弊类型 1-超过切屏次数视为作弊,2-超过考试时间无交互视为作弊
     * @param userExamId 用户考试ID
     * @param req
     * @return
     */
    @PostMapping("/setCheat/{cheatType}/{userExamId}")
    public ActionResult<Boolean> setCheat(@PathVariable("cheatType") Integer cheatType,
                                          @PathVariable("userExamId") String userExamId,
                                          @RequestBody @Valid SubExamQuestionReq req) throws Exception {

        String lockKey = "subExam" + userExamId;
        String lockValue = UUID.randomUUID().toString();
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 10, TimeUnit.SECONDS);
        if (Boolean.TRUE.equals(lock)) {
            try {
                examUserService.setCheat(userExamId, cheatType, req);
                return ActionResult.success(true);
            } catch (Exception e) {
                // ✔ 建议加日志
                log.error("setCheat异常 userExamId: {}, cheatType: {}", userExamId, cheatType, e);
                throw e;
            } finally {
                // ✔ 防止误删锁（关键）
                Object value = redisTemplate.opsForValue().get(lockKey);
                if (null != value && lockValue.equals(value.toString())) {
                    redisTemplate.delete(lockKey);
                }
            }
        } else {
            throw new RuntimeException("请不要重复提交");
        }
    }

    /**
     * 根据考试id查询考试整体结果
     *
     * @param userExamId 用户考试id
     * @return
     */
    @GetMapping("/queryExamResult/{userExamId}")
    public ActionResult<AppExamUserVo> queryExamResult(@PathVariable("userExamId") String userExamId) {
        UserExamDetailVo examVo = examUserService.getUserExamDetail(userExamId, false);
        AppExamUserVo vo = BeanUtil.copyProperties(examVo, AppExamUserVo.class);
        //计算正确lv 和错误lv
        int totleNum = vo.getQuestionNumber();
        int correctNum = vo.getCorrectCount();
        int errorNum = totleNum - correctNum;
        if(errorNum<=0){
            errorNum=0;
        }
        vo.setErrorCount(errorNum);
        vo.setCorrectLv(QuestionAnalysisUtil.calculatePercentage(correctNum, totleNum) + "");
        vo.setErrorLv(QuestionAnalysisUtil.calculatePercentage(errorNum, totleNum) + "");
        return ActionResult.success(vo);
    }

    /**
     * 根据考试id查询考试试题结果列表
     *
     * @param userExamId 用户考试id
     * @return
     */
    @GetMapping("/queryExamQuestionList/{userExamId}")
    public ActionResult<Map<String, List<UserQuestionVo>>> queryExamQuestionList(@PathVariable("userExamId") String userExamId) {
        UserExamDetailVo examVo = examUserService.getUserExamDetail(userExamId, true);
        return ActionResult.success(examVo.getQuestionMap());
    }


    /**
     * 查询我的考试列表
     *
     * @param req
     * @return
     */
    @GetMapping("/queryMyExamList")
    public ActionResult<PageListVO<AppExamListVo>> queryMyExamList(@Valid QueryExamListReq req) {
        PageInfo<AppExamListVo> pageVo = examUserService.queryMyExamList(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

    /**
     * 查询我的岗位考试列表（完成考试合格且需要考试合格才能鉴定 切未鉴定的岗位）
     *
     * @return
     */
    @GetMapping("/queryAlertPostionIdentify")
    public ActionResult<List<PositionEntity>> queryAlertPostionIdentify() {
        return ActionResult.success(examUserService.queryAlertPostionIdentify(UserProvider.getLoginUserId()));
    }


    /**
     * 删除我的考试记录（已经作废的常规考试）
     *
     * @param userExamId 用户考试ID,以逗号分开
     * @return
     */
    @GetMapping("/hiddenMyExamRecord/{userExamId}")
    public ActionResult<Boolean> hiddenMyExamRecord(@PathVariable("userExamId") String userExamId) {
        examUserService.hiddenMyExamRecord(userExamId);
        return ActionResult.success(true);
    }

    /**
     * 查询我下属考试数量，用于是否展示Tab
     *
     * @return
     */
    @GetMapping("/queryMyBlowExamNum")
    public ActionResult<MyBlowExamNum> queryMyBlowExamNum() {
        return ActionResult.success(examUserService.queryMyBlowExamNum());
    }


    /**
     * 待我批阅(下属的)
     *
     * @param req
     * @return
     */
    @GetMapping("/queryWaitMyReadOver")
    public ActionResult<PageListVO<AppExamListVo>> queryWaitMyReadOver(@Valid QueryExamListReq req) {
        PageInfo<AppExamListVo> pageVo = examUserService.queryWaitMyReadOver(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

    /**
     * 我完成的批阅（下属的）
     *
     * @param req
     * @return
     */
    @GetMapping("/queryMyCompleteReadOver")
    public ActionResult<PageListVO<AppExamListVo>> queryMyCompleteReadOver(@Valid QueryExamListReq req) {
        PageInfo<AppExamListVo> pageVo = examUserService.queryMyCompleteReadOver(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }


    /**
     * 逾期未考（下属的）
     *
     * @param req
     * @return
     */
    @GetMapping("/expireExam")
    public ActionResult<PageListVO<AppExamListVo>> expireExam(QueryExpireListReq req) {
        PageInfo<AppExamListVo> pageVo = examUserService.expireExam(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }


    /**
     * 清除逾期未考（下属的）
     *
     * @param userExamIds 用户考试ID,以逗号分开
     * @return
     */
    @GetMapping("/clearExpireExam")
    public ActionResult<Boolean> clearExpireExam(@RequestParam("userExamIds") String userExamIds) {
        examUserService.clearExpireExam(userExamIds);
        return ActionResult.success(true);
    }

    /**
     * 批阅考试
     *
     * @param req
     * @return
     */
    @PostMapping("/readOver")
    public ActionResult<Boolean> readOver(@RequestBody @Valid ReadOverExamReq req) {
        FtbCultivateExamUser examUser = examUserService.getById(req.getUserExamId());
        if (null == examUser || examUser.getEnabledMark() == 0) {
            return ActionResult.fail(1000, "考试记录已经删除");
        }
        examUserService.readOver(req);
        return ActionResult.success(true);
    }

    /**
     * 考试排行版
     *
     * @param examId 考试id
     * @return
     */
    @GetMapping("/ranking/{examId}")
    public ActionResult<PageListVO<UserRankingVo>> rankingList(@PathVariable("examId") String examId,
                                                               QueryExamRankListReq req) {
        PageInfo<UserRankingVo> pageVo = examUserService.rankIngList(examId, req);

        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));

    }

    /**
     * 查询我在这次考试的数据
     *
     * @param examId 考试id
     * @return
     */
    @GetMapping("/ranking/my/{examId}")
    public ActionResult<UserRankingVo> queryMyRank(@PathVariable("examId") String examId) {
        return ActionResult.success(examUserService.queryMyRank(examId));

    }


    /**
     * 培训功能优化,统计组织下用户考试合格率、合格人数、考试总人数
     *
     * @param dto
     * @return
     */
    @GetMapping("/queryCultivateCout")
    public ActionResult<ExamCultivateCountVo> queryCultivateCout(CultivateUserExamCountDTO dto) {
        return ActionResult.success(examUserService.queryCultivateCount(dto, new ArrayList<>()));
    }


    /**
     * 根据岗位ID，统计 岗位考试人数、优秀人数、合格人数、不合格人数
     *
     * @param positionId 岗位ID
     * @return
     */
    @GetMapping("/queryCultivateCountForPositionId")
    public ActionResult<ExamCultivateForPositionVo> queryCultivateCountForPositionId(String positionId) {
        return ActionResult.success(examUserService.queryCultivateCountForPositionId(positionId));
    }


    /**
     * 员工首页-查询考试成绩列表
     *
     * @param req
     * @return
     */
    @GetMapping("/queryCultivateExamList")
    public ActionResult<PageListVO<MyExamListVo>> queryCultivateExamList(@Valid QueryCultivateExamReq req) {
        String loginUserId = UserProvider.getLoginUserId();
        if (StringUtils.isEmpty(req.getUserId())) {
            req.setUserId(loginUserId);
        }
        PageInfo<MyExamListVo> pageVo = examUserService.queryExamList(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

}
