package com.cirle.scientific.controller.miniapp;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.cirle.scientific.dao.QkjExamineRecordAppDao;
import com.cirle.scientific.dao.QkjLungReportUnderstandAppDao;
import com.cirle.scientific.dao.QkjStudyRecordAppDao;
import com.cirle.scientific.dto.course.*;
import com.cirle.scientific.dto.qkjquestionoption.QkjQuestionOptionAppDTO;
import com.cirle.scientific.dto.questiondetail.QkjQuestionDetailAppDTO;
import com.cirle.scientific.po.QkjExamineRecordApp;
import com.cirle.scientific.po.QkjLungReportUnderstandApp;
import com.cirle.scientific.po.QkjQuestionAnswerApp;
import com.cirle.scientific.po.QkjStudyRecordApp;
import com.cirle.scientific.pojo.BizCodeEnum;
import com.cirle.scientific.pojo.Result;
import com.cirle.scientific.service.*;
import com.cirle.scientific.utils.LocalDateTimeUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Controller
@RequiredArgsConstructor
@RequestMapping("/app/course")
@Api("课程学习相关接口")
@Slf4j
public class CourseStudyController {

    private final CourseAppService courseAppService;
    private final QuestionAnswerAppService questionAnswerAppService;
    private final QkjExamineRecordAppDao qkjExamineRecordAppDao;
    private final QkjStudyRecordAppDao qkjStudyRecordAppDao;
    private final QkjLungReportUnderstandAppDao qkjLungReportUnderstandAppDao;
    private final LungReportUnderstandAppService lungReportUnderstandAppService;
    private final QuestionAppService questionAppService;
    private final QuestionnaireService questionnaireService;

    @GetMapping("/getCourseList")
    @ResponseBody
    @ApiOperation(value = "获取理论课程和技能知识学习列表接口 ")
    public Result<List<CourseAppListDTO>> getCourseList(@ApiParam(name = "memCard", value = "用户唯一标识") @RequestAttribute(name = "memCard", required = false) String memCard,
                                                        @ApiParam(name = "type", value = "课程类型 1:理论 2: 技能") @RequestParam(name = "type") Integer type
    ) {
        return Result.success(courseAppService.getCourseList(memCard, type));
    }

    @GetMapping("/details")
    @ResponseBody
    @ApiOperation(value = "获取理论课程和技能知识学习详情接口 ")
    public Result<CourseAppDetailsDTO> getCourseDetails(@RequestAttribute(name = "memCard", required = false) String memCard,
                                                        @ApiParam(name = "id", value = "课程id") @RequestParam(name = "id") Long id
    ) {
        return Result.success(courseAppService.getCourseDetails(id, memCard));
    }

    @GetMapping("/save/study/record")
    @ResponseBody
    @ApiOperation(value = "保存进度接口")
    public Result<QkjStudyRecordApp> saveRecord(@ApiParam(name = "memCard", value = "用户唯一标识") @RequestAttribute(name = "memCard", required = false) String memCard,
                                                @ApiParam(name = "objId", value = "课程ID") @RequestParam(name = "objId") Long objId,
                                                @ApiParam(name = "objType", value = "类型1：理论课程 2 ：技能课程") @RequestParam(name = "objType") Integer objType,
                                                @ApiParam(name = "studyAccomplish", value = "是否看完 0：未看完 1：已看完") @RequestParam(name = "studyAccomplish") Integer studyAccomplish
    ) {
        log.info("saveRecord memCard:{} objId:{} objType:{} studyAccomplish:{}", memCard, objId, objType, studyAccomplish);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        QkjStudyRecordApp qkjStudyRecordApp = courseAppService.saveStudyRecord(memCard, objId, studyAccomplish, objType);
        return Result.success(qkjStudyRecordApp);
    }

    @GetMapping("/save/study/record/progress")
    @ResponseBody
    @ApiOperation(value = "保存进度接口时长")
    public Result<QkjStudyRecordApp> saveRecordProgress(@ApiParam(name = "memCard", value = "用户唯一标识") @RequestAttribute(name = "memCard", required = false) String memCard,
                                                        @ApiParam(name = "objId", value = "课程ID") @RequestParam(name = "objId") Long objId,
                                                        @ApiParam(name = "objType", value = "类型1：理论课程 2 ：技能课程") @RequestParam(name = "objType") Integer objType,
                                                        @ApiParam(name = "duration", value = "总时长") @RequestParam(name = "duration") Integer duration,
                                                        @ApiParam(name = "currentTime", value = "当前时长") @RequestParam(name = "currentTime") Integer currentTime
    ) {
        log.info("saveRecordProgress memCard:{} objId:{} objType:{} duration:{} currentTime:{}", memCard, objId, objType, duration, currentTime);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        QkjStudyRecordApp qkjStudyRecordApp = courseAppService.saveRecordProgress(memCard, objId, objType, duration, currentTime);
        return Result.success(qkjStudyRecordApp);
    }


    @GetMapping("/init/study/record")
    @ResponseBody
    @ApiOperation(value = "初始化学习进度")
    public Result<QkjStudyRecordApp> initRecord(@ApiParam(name = "memCard", value = "用户唯一标识") @RequestAttribute(name = "memCard", required = false) String memCard,
                                                @ApiParam(name = "objId", value = "课程ID") @RequestParam(name = "objId") Long objId,
                                                @ApiParam(name = "objType", value = "类型1：理论课程 2 ：技能课程") @RequestParam(name = "objType") Integer objType
    ) {
        log.info("initRecord memCard:{} objId:{} objType:{}", memCard, objId, objType);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        QkjStudyRecordApp qkjStudyRecordApp = courseAppService.initStudyRecord(memCard, objId, objType);
        return Result.success(qkjStudyRecordApp);
    }


    @GetMapping("/saveCommon")
    @ResponseBody
    @ApiOperation(value = "保存用户留言")
    public Result saveCommon(@RequestAttribute(value = "memCard", required = false) String memCard,
                             @ApiParam(name = "content", value = "content") @RequestParam(value = "content", required = false) String content,
                             @RequestParam(name = "objId") Long objId
    ) {
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        return courseAppService.saveCommonApp(objId, memCard, content);
    }

    @GetMapping("/getCommon")
    @ResponseBody
    @ApiOperation(value = "获取用户留言")
    public Result getCommon(@RequestParam(name = "id", required = true) Long id
    ) {
        return Result.success(courseAppService.getComment(id));
    }

    @GetMapping("/get/random/question")
    @ResponseBody
    @ApiOperation(value = "获取随机试题")
    public Result getRandomQuestion(@RequestAttribute(value = "memCard", required = false) String memCard) {
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }

        Map<Integer, List<QkjQuestionDetailAppDTO>> mapResult = Maps.newHashMap();
        //查询该人是否回答过理论考试的题
        List<QkjQuestionAnswerApp> questionAnswer = questionAnswerAppService.findQuestionAnswer(memCard, 2);
        QkjExamineRecordApp recordApp = qkjExamineRecordAppDao.getByMemCard(memCard, 1);
        if (CollectionUtil.isNotEmpty(questionAnswer) && Objects.nonNull(recordApp) && Objects.equals(1, recordApp.getSaveType())) {
            Map<Integer, Integer> collect = questionAnswer.stream().collect(Collectors.toMap(QkjQuestionAnswerApp::getQuId, QkjQuestionAnswerApp::getOptionId));
            Map<Integer, List<QkjQuestionDetailAppDTO>> map = questionnaireService.findQuestionszByExId(questionAnswer.get(0).getObjId());
            log.info("getRandomQuestion collect:{} map:{}", collect, map);
            map.forEach((k, v) -> {
                v.forEach(o -> {
                    Integer optionId = collect.getOrDefault(o.getQuId(), null);
                    if (Objects.nonNull(optionId)) {
                        List<QkjQuestionOptionAppDTO> option = o.getOption();
                        for (QkjQuestionOptionAppDTO dto : option) {
                            if (dto.getOptionId().intValue() == optionId) {
                                dto.setChecked(true);
                            }
                        }
                        o.setOption(option);
                    }
                });
                mapResult.put(k, v);
            });
            log.info("getRandomQuestion mapResult:{}", mapResult);
        }
        if (MapUtils.isNotEmpty(mapResult)) {
            return Result.success(mapResult);
        }
        return Result.success(courseAppService.getRandomQuestion(memCard));
    }

    @GetMapping("/save/question/skill")
    @ResponseBody
    @ApiOperation(value = "技能考核保存")
    public Result saveQuestionSkill(@RequestAttribute(value = "memCard", required = false) String memCard,
                                    @ApiParam(name = "url", value = "技能考核的路径") @RequestParam(name = "url") String url) {
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }

        QkjExamineRecordApp recordAppOld = qkjExamineRecordAppDao.getByMemCard(memCard, 2);
        if (Objects.nonNull(recordAppOld)) {
            qkjExamineRecordAppDao.deleteById(recordAppOld.getId());
        }
        QkjExamineRecordApp recordApp = new QkjExamineRecordApp();
        recordApp.setType(2);
        recordApp.setUrl(url);
        recordApp.setMemCard(memCard);
        recordApp.setResult(0);
        QkjExamineRecordApp save = qkjExamineRecordAppDao.save(recordApp);
        return Result.success(save.getId());
    }

    @PostMapping("/save/question")
    @ResponseBody
    @ApiOperation(value = "保存试卷")
    public Result saveQuestion(@RequestAttribute(value = "memCard", required = false) String memCard,
                               @RequestBody List<QkjQuestionAnswerApp> questionAnswerApp) {
        log.info("saveQuestion questionAnswerApp:{}", questionAnswerApp);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }

        Map<String, Object> mapResult = Maps.newHashMap();

        //计算分数
        int score = 0;
        //错误提示
        List<WrongQuestionAnalysisDTO> wrongQuestionAnalysisDTOs = Lists.newArrayList();

        try {
            List<RightDTO> rightDTOS = questionAppService.listRightDTO(questionAnswerApp.get(0).getObjId());
            Map<Integer, RightDTO> rightDTOMap = rightDTOS.stream().collect(Collectors.toMap(RightDTO::getQuId, e -> e, (v1, v2) -> v1));
            for (QkjQuestionAnswerApp answerApp : questionAnswerApp) {
                Integer quId = answerApp.getQuId();
                RightDTO rightDTO = rightDTOMap.get(quId);
                if (Objects.equals(rightDTO.getOptionId() ,answerApp.getOptionId())) {
                    score = score + rightDTO.getScore();
                } else {
                    WrongQuestionAnalysisDTO build = WrongQuestionAnalysisDTO.builder()
                            .quId(quId)
                            .quTitle(rightDTO.getQuTitle())
                            .optionId(rightDTO.getOptionId())
                            .optionTitle(rightDTO.getOptionTitle())
                            .option(rightDTO.getOption())
                            .analysis(rightDTO.getAnalysis())
                            .build();
                    wrongQuestionAnalysisDTOs.add(build);
                }
            }
        } catch (Exception e) {
            log.error("计算分数出错 err:{}", e);
        }

        //增加 回答表
        boolean save = true;
        //如果当前的分数比之前的低就不更新分数了 也不保存答案
        QkjExamineRecordApp recordAppOld = qkjExamineRecordAppDao.getByMemCard(memCard, 1);
        if (Objects.nonNull(recordAppOld) && Objects.nonNull(recordAppOld.getScore()) && score < recordAppOld.getScore()) {
            save = false;
        }

        questionAnswerApp = questionAnswerApp.stream().filter(e -> Objects.nonNull(e.getOptionId())).collect(Collectors.toList());
        for (QkjQuestionAnswerApp answerApp : questionAnswerApp) {
            answerApp.setMemCard(memCard);
            answerApp.setType(2);
            answerApp.setQuType(0);
        }
        if (save) {
            int result = questionAnswerAppService.addQuestionAnswerForYs(questionAnswerApp);
            if (result == 200) {
                if (Objects.nonNull(recordAppOld)) {
                    qkjExamineRecordAppDao.deleteById(recordAppOld.getId());
                }
                QkjExamineRecordApp recordApp = new QkjExamineRecordApp();
                recordApp.setType(1);
                recordApp.setMemCard(memCard);
                recordApp.setScore(score);
                recordApp.setSaveType(2);
                qkjExamineRecordAppDao.save(recordApp);
            }

        } else {
            recordAppOld.setSaveType(2);
            qkjExamineRecordAppDao.save(recordAppOld);
        }
        mapResult.put("score", score);

        //错题分析
        mapResult.put("analysis", wrongQuestionAnalysisDTOs);
        return Result.success(mapResult);
    }


    @PostMapping("/save/question/temporarily")
    @ResponseBody
    @ApiOperation(value = "暂时存试卷")
    public Result saveQuestionTemporarily(@RequestAttribute(value = "memCard", required = false) String memCard,
                                          @RequestBody List<QkjQuestionAnswerApp> questionAnswerApp) {
        log.info("saveQuestionTemporarily questionAnswerApp:{}", questionAnswerApp);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        questionAnswerApp = questionAnswerApp.stream().filter(e -> Objects.nonNull(e.getOptionId())).collect(Collectors.toList());
        for (QkjQuestionAnswerApp answerApp : questionAnswerApp) {
            answerApp.setMemCard(memCard);
            answerApp.setType(2);
            answerApp.setQuType(0);
        }
        //一个人一套试题只存在一个回答，之前的山掉
        int result = questionAnswerAppService.addQuestionAnswerForYs(questionAnswerApp);
        if (result == 200) {
            QkjExamineRecordApp recordApp = qkjExamineRecordAppDao.getByMemCard(memCard, 1);
            if (Objects.isNull(recordApp)) {
                recordApp = new QkjExamineRecordApp();
            }

            recordApp.setType(1);
            recordApp.setMemCard(memCard);
            recordApp.setSaveType(1);
            qkjExamineRecordAppDao.save(recordApp);
        }
        return Result.success(BizCodeEnum.SUCCESS);
    }

    @GetMapping("/join/theory/examination")
    @ResponseBody
    @ApiOperation(value = "是否进行过理论考试")
    public Result joinTheoryExamination(@RequestAttribute(value = "memCard", required = false) String memCard) {
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        boolean finishCourse = false;
        List<CourseAppListDTO> courseList = courseAppService.getCourseList(memCard, 1);
        if (CollectionUtil.isNotEmpty(courseList)) {
            int finishSize = 0;
            List<Long> ids = courseList.stream().map(CourseAppListDTO::getId).collect(Collectors.toList());
            List<QkjStudyRecordApp> recordApps = qkjStudyRecordAppDao.findByMemCardAndObjIdsAndType(memCard, ids, 1);
            if (CollectionUtil.isNotEmpty(recordApps)) {
                for (QkjStudyRecordApp qkjStudyRecordApp : recordApps) {
                    if (Objects.equals(qkjStudyRecordApp.getStudyAccomplish(), 1)) {
                        finishSize = finishSize + 1;
                    }
                }
            }
            log.info("joinTheoryExamination courseList:{} finishSize:{}", courseList.size(), finishSize);
            finishCourse = finishSize == courseList.size();
        }
        QkjExamineRecordApp recordApp = qkjExamineRecordAppDao.getByMemCard(memCard, 1);
        JoinExaminationDTO build = JoinExaminationDTO.builder()
                .finishCourse(finishCourse)
                .recordApp(recordApp)
                .build();
        return Result.success(build);
    }

    @GetMapping("/join/skill/examination")
    @ResponseBody
    @ApiOperation(value = "是否进行过技能考试")
    public Result joinSkillExamination(@RequestAttribute(value = "memCard", required = false) String memCard) {
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }

        boolean finishCourse = false;
        List<CourseAppListDTO> courseList = courseAppService.getCourseList(memCard, 2);
        if (CollectionUtil.isNotEmpty(courseList)) {
            int finishSize = 0;
            List<Long> ids = courseList.stream().map(CourseAppListDTO::getId).collect(Collectors.toList());
            List<QkjStudyRecordApp> recordApps = qkjStudyRecordAppDao.findByMemCardAndObjIdsAndType(memCard, ids, 2);
            if (CollectionUtil.isNotEmpty(recordApps)) {
                for (QkjStudyRecordApp qkjStudyRecordApp : recordApps) {
                    if (Objects.equals(qkjStudyRecordApp.getStudyAccomplish(), 1)) {
                        finishSize = finishSize + 1;
                    }
                }
            }
            finishCourse = courseList.size() == finishSize;
            log.info("joinSkillExamination courseList:{} finishSize:{}", courseList.size(), finishSize);
        }
        QkjExamineRecordApp recordApp = qkjExamineRecordAppDao.getByMemCard(memCard, 2);
        JoinExaminationDTO build = JoinExaminationDTO.builder()
                .finishCourse(finishCourse)
                .recordApp(recordApp)
                .build();
        return Result.success(build);
    }

    @GetMapping("/delete/skill/examination")
    @ResponseBody
    @ApiOperation(value = "删除技能考试")
    public Result deleteSkillExamination(@RequestAttribute(value = "memCard", required = false) String memCard) {

        QkjExamineRecordApp recordApp = qkjExamineRecordAppDao.getByMemCard(memCard, 2);
        qkjExamineRecordAppDao.delete(recordApp);
        return Result.success(BizCodeEnum.SUCCESS);
    }

    @PostMapping("/lung/report/understanding/upload")
    @ResponseBody
    @ApiOperation(value = "肺功能报告解读上传接口")
    public Result lungReportUpload(@RequestAttribute(value = "memCard", required = false) String memCard,
                                   @RequestBody List<LungReportUploadReq> lungReportUploadReqList
    ) {
        log.info("lungReportUpload memCard:{} lungReportUploadReqList:{}", memCard, lungReportUploadReqList);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        List<QkjLungReportUnderstandApp> list = Lists.newArrayList();
        for (LungReportUploadReq req : lungReportUploadReqList) {
            if (Objects.isNull(req)) {
                continue;
            }
            if (Objects.isNull(req.getId())) {
                QkjLungReportUnderstandApp reportUnderstandApp = new QkjLungReportUnderstandApp();
                reportUnderstandApp.setMemCard(memCard);
                reportUnderstandApp.setImgUrl(req.getImgUrl());
                reportUnderstandApp.setUnderstand(req.getUnderstand());
                reportUnderstandApp.setStatus(0);
                list.add(reportUnderstandApp);
            } else {
                QkjLungReportUnderstandApp understandApp = qkjLungReportUnderstandAppDao.findById(req.getId()).orElse(null);
                if (Objects.nonNull(understandApp)) {
                    understandApp.setImgUrl(req.getImgUrl());
                    understandApp.setUnderstand(req.getUnderstand());
                    understandApp.setAppraise(req.getAppraise());
                    understandApp.setStatus(req.getStatus());

                    list.add(understandApp);
                }
            }
        }
        qkjLungReportUnderstandAppDao.saveAll(list);
        return Result.success(BizCodeEnum.SUCCESS);
    }

    @PostMapping("/lung/report/understanding/get")
    @ResponseBody
    @ApiOperation(value = "肺功能报告解读查询接口")
    public Result lungReportList(@RequestAttribute(value = "memCard", required = false) String memCard) {
        log.info("lungReportList memCard:{}", memCard);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        return Result.success(lungReportUnderstandAppService.lungReportList(memCard));
    }

    @GetMapping("/study/record/list")
    @ResponseBody
    @ApiOperation(value = "学习记录接口")
    public Result studyRecordList(@RequestAttribute(value = "memCard", required = false) String memCard,
                                  @ApiParam(name = "type", value = "1:理论 2：技能") @RequestParam(name = "type") Integer type) {
        log.info("lungReportList memCard:{} type:{}", memCard, type);
        if (StringUtils.isBlank(memCard)) {
            return Result.failed(BizCodeEnum.NO_LOGIN);
        }
        List<CourseAppListDTO> result = Lists.newArrayList();
        List<QkjStudyRecordApp> recordApps = qkjStudyRecordAppDao.findByMemCardAndType(memCard, type);
        if (CollectionUtil.isEmpty(recordApps)) {
            return Result.success(result);
        }
        List<Long> collect = recordApps.stream().map(QkjStudyRecordApp::getObjId).collect(Collectors.toList());
        Map<Long, QkjStudyRecordApp> objIdToObjetMap = recordApps.stream().collect(Collectors.toMap(QkjStudyRecordApp::getObjId, e -> e));
        List<CourseAppListDTO> courseList = courseAppService.getCourseList(memCard, type);
        result = courseList.stream().filter(e -> Objects.nonNull(e.getId()) && collect.contains(e.getId())).collect(Collectors.toList());
        for (CourseAppListDTO courseAppListDTO : result) {
            QkjStudyRecordApp recordApp = objIdToObjetMap.getOrDefault(courseAppListDTO.getId(), new QkjStudyRecordApp());
            courseAppListDTO.setCurrentTimeString(LocalDateTimeUtil.secondsToTime(recordApp.getPresentTime()));
            courseAppListDTO.setDurationString(LocalDateTimeUtil.secondsToTime(recordApp.getDuration()));
            courseAppListDTO.setDuration(recordApp.getDuration());
            courseAppListDTO.setCurrentTime(recordApp.getPresentTime());
            courseAppListDTO.setStudyAccomplish(recordApp.getStudyAccomplish());

        }
        return Result.success(result);
    }


}
