package com.qxgmat.controller.api;


import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.nuliji.tools.*;
import com.nuliji.tools.exception.ParameterException;
import com.qxgmat.data.constants.enums.logic.ExerciseLogic;
import com.qxgmat.data.constants.enums.module.PaperModule;
import com.qxgmat.data.constants.enums.module.PayModule;
import com.qxgmat.data.dao.entity.*;
import com.qxgmat.data.relation.entity.UserExercisePaperRelation;
import com.qxgmat.data.relation.entity.UserHomeworkPreviewRelation;
import com.qxgmat.data.relation.entity.UserReportRelation;
import com.qxgmat.dto.extend.QuestionExtendDto;
import com.qxgmat.dto.extend.QuestionNoExtendDto;
import com.qxgmat.dto.extend.UserExercisePaperExtendDto;
import com.qxgmat.dto.extend.UserHomeworkPreviewExtendDto;
import com.qxgmat.dto.request.*;
import com.qxgmat.dto.response.*;
import com.qxgmat.help.ShiroHelp;
import com.qxgmat.service.*;
import com.qxgmat.service.extend.QuestionFlowService;
import com.qxgmat.service.inline.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/question")
@Api(tags = "题目", description = "题目接口")
public class QuestionController {

    @Autowired
    private ShiroHelp shiroHelp;

    @Autowired
    private HomeworkPreviewService homeworkPreviewService;

    @Autowired
    private ExercisePaperService exercisePaperService;

    @Autowired
    private QuestionNoService questionNoService;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private UserQuestionService userQuestionService;

    @Autowired
    private UserCollectQuestionService userCollectQuestionService;

    @Autowired
    private UserClassService userClassService;

    @Autowired
    private UserPayService userPayService;

    @Autowired
    private UserReportService userReportService;

    @Autowired
    private UserPaperService userPaperService;

    @Autowired
    private QuestionFlowService questionFlowService;

    @RequestMapping(value = "/class/process", method = RequestMethod.GET)
    @ApiOperation(value = "获取课程进度", notes = "获取所有课程及状态进度", httpMethod = "GET")
    public Response<List<UserClassDetailDto>> classProcess()  {
        User user = (User) shiroHelp.getLoginUser();
        List<UserClass> userClassList = userClassService.getByUser(user.getId());
        List<UserClassDetailDto> dtos = Transform.convert(userClassList, UserClassDetailDto.class);

        // 获取每个科目的最后2次作业
        Map<Object, Collection<UserHomeworkPreviewRelation>> previewMap = homeworkPreviewService.groupByCategory(user.getId(), 3);
        Transform.combine(dtos, previewMap, UserClassDetailDto.class, "category", "previews", UserHomeworkPreviewExtendDto.class);

        // 获取课程状态：已购买未开通
        List<UserPay> pays = userPayService.listUnUse(user.getId(), PayModule.CLASS);
        Collection ids = Transform.getIds(userClassList, UserClass.class, "category");
        for(UserPay pay : pays){
            Integer category = Integer.valueOf(pay.getModuleExtend());
            if (!ids.contains(category)){
                UserClassDetailDto dto = new UserClassDetailDto();
                dto.setCategory(category);
                dto.setPayed(true);
                dtos.add(dto);
            }
        }

        return ResponseHelp.success(dtos);
    }

    @RequestMapping(value = "/preview/list", method = RequestMethod.GET)
    @ApiOperation(value = "获取预习作业列表", notes = "获取预习作业列表", httpMethod = "GET")
    public Response<PageMessage<UserHomeworkPreviewExtendDto>> listPreview(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = false) Number category,
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false) Boolean finish
    )  {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserHomeworkPreviewRelation> p = homeworkPreviewService.list(page, size, category, user.getId(), endTime, finish);

        List<UserHomeworkPreviewExtendDto> pr = Transform.convert(p, UserHomeworkPreviewExtendDto.class);

        // 获取试卷统计信息
        Map map = Transform.getMap(p, UserHomeworkPreviewRelation.class, "id", "preview");
        Map<Integer, Integer[]> questionNoIdsMap = new HashMap<>();
        for(Object value : map.keySet()){
            Integer key = (Integer) value;
            HomeworkPreview preview = (HomeworkPreview) map.get(key);
            questionNoIdsMap.put(key, preview.getQuestionNoIds());
        }
        Map statMap = questionNoService.statPaperMap(questionNoIdsMap);
        Transform.combine(pr, statMap, UserHomeworkPreviewExtendDto.class, "id", "stat");

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/exercise/process", method = RequestMethod.GET)
    @ApiOperation(value = "练习进度", httpMethod = "GET")
    public Response<List<UserExerciseGroupDto>> exerciseProcess(
            @RequestParam(required = true) Integer structId, // 第三层，查询第4层，以及第三层汇总
            HttpSession session) {
        Page<UserExerciseGroupDto> p=null;

        // todo 获取数据

        return ResponseHelp.success(p);
    }

    @RequestMapping(value = "/exercise/place", method = RequestMethod.GET)
    @ApiOperation(value = "练习组卷考点分组条件", httpMethod = "GET")
    public Response<List<String>> exercisePlace(HttpSession session) {
        return ResponseHelp.success(exercisePaperService.groupPlace());
    }

    @RequestMapping(value = "/exercise/list", method = RequestMethod.GET)
    @ApiOperation(value = "练习组卷列表", httpMethod = "GET")
    public Response<PageMessage<UserExercisePaperExtendDto>> listExercisePaper(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) Integer structId,
            @RequestParam(required = true) String logic,
            @RequestParam(required = false, name = "logic_extend") String logicExtend,
            @RequestParam(required = false)  Integer times,
            HttpSession session) {
        User user = (User) shiroHelp.getLoginUser();
        PageResult<UserExercisePaperRelation> p = exercisePaperService.list(page, size, structId, user.getId(), ExerciseLogic.ValueOf(logic), logicExtend, times);

        List<UserExercisePaperExtendDto> pr = Transform.convert(p, UserExercisePaperExtendDto.class);

        // 获取试卷统计信息
        Map map = Transform.getMap(p, UserExercisePaperRelation.class, "id", "paper");
        Map<Integer, Integer[]> questionNoIdsMap = new HashMap<>();
        for(Object value : map.keySet()){
            Integer key = (Integer) value;
            ExercisePaper paper = (ExercisePaper) map.get(key);
            questionNoIdsMap.put(key, paper.getQuestionNoIds());
        }
        Map statMap = questionNoService.statPaperMap(questionNoIdsMap);
        Transform.combine(pr, statMap, UserHomeworkPreviewExtendDto.class, "id", "stat");

        return ResponseHelp.success(pr, page, size, p.getTotal());
    }

    @RequestMapping(value = "/examination/process", method = RequestMethod.GET)
    @ApiOperation(value = "模考进度", httpMethod = "GET")
    public Response<PageMessage<ExercisePaper>> examinationProcess(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            HttpSession session) {
        Page<ExercisePaper> p = null;

        // todo

        return ResponseHelp.success(p, page, size, p.getTotal());
    }

    @RequestMapping(value = "/examination/list", method = RequestMethod.GET)
    @ApiOperation(value = "模考组卷列表", httpMethod = "GET")
    public Response<PageMessage<ExercisePaper>> examinationPaperList(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            HttpSession session) {
        Page<ExercisePaper> p = null;

        // todo

        return ResponseHelp.success(p, page, size, p.getTotal());
    }

    @RequestMapping(value = "/question/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取题目详情", notes = "获取题目详情", httpMethod = "GET")
    public Response<UserQuestionDetailDto> detail(
            @RequestParam(required = true, name="id") Integer userQuestionId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        // todo 获取数据

        return ResponseHelp.success(null);
    }

    @RequestMapping(value = "/exercise/paper", method = RequestMethod.GET)
    @ApiOperation(value = "获取练习卷", notes = "获取练习卷", httpMethod = "GET")
    public Response<PaperBaseDto> detailExercise(
            @RequestParam(required = true, name="id") Integer paperId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        ExercisePaper paper = exercisePaperService.get(paperId);
        PaperBaseDto paperDto = Transform.convert(paper, PaperBaseDto.class);

        return ResponseHelp.success(paperDto);
    }

    @RequestMapping(value = "/report/base", method = RequestMethod.GET)
    @ApiOperation(value = "获取练习记录", notes = "获取练习卷", httpMethod = "GET")
    public Response<UserReportBaseDto> baseReport(
            @RequestParam(required = true, name="id") Integer userReportId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        UserReportRelation report = questionFlowService.baseReport(user.getId(), userReportId);

        UserReportBaseDto userReportDto = Transform.convert(report, UserReportBaseDto.class);

        return ResponseHelp.success(userReportDto);
    }

    @RequestMapping(value = "/report/detail", method = RequestMethod.GET)
    @ApiOperation(value = "获取练习详细记录", notes = "获取练习卷", httpMethod = "GET")
    public Response<UserReportDetailDto> detailReport(
            @RequestParam(required = true, name="id") Integer userReportId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        UserReportRelation report = questionFlowService.baseReport(user.getId(), userReportId);

        UserReportDetailDto userReportDto = Transform.convert(report, UserReportDetailDto.class);

        return ResponseHelp.success(userReportDto);
    }

    @RequestMapping(value = "/exercise/start", method = RequestMethod.POST)
    @ApiOperation(value = "开始: 练习", notes = "提交考试设置", httpMethod = "POST")
    public Response<UserReportBaseDto> startExercise(@RequestBody @Validated ExerciseStartDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        JSONObject setting = new JSONObject();
        setting.put("disorder", dto.getDisorder());
        UserReport report = questionFlowService.start(user.getId(), PaperModule.HOMEWORK_PREVIEW, dto.getPaperId(), setting);

        return ResponseHelp.success(Transform.convert(report, UserReportBaseDto.class));
    }

    @RequestMapping(value = "/preview/paper", method = RequestMethod.GET)
    @ApiOperation(value = "获取预习作业", notes = "获取预习作业", httpMethod = "GET")
    public Response<PaperBaseDto> detailPreview(
            @RequestParam(required = true, name="id") Integer paperId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        HomeworkPreview preview = homeworkPreviewService.get(paperId);
        PaperBaseDto paperDto = Transform.convert(preview, PaperBaseDto.class);

        return ResponseHelp.success(paperDto);
    }

    @RequestMapping(value = "/preview/start", method = RequestMethod.POST)
    @ApiOperation(value = "开始: 预习作业", notes = "提交考试设置", httpMethod = "POST")
    public Response<UserReportBaseDto> startPreview(@RequestBody @Validated PreviewStartDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        JSONObject setting = new JSONObject();
        setting.put("disorder", dto.getDisorder());
        UserReportRelation report = questionFlowService.start(user.getId(), PaperModule.HOMEWORK_PREVIEW, dto.getPaperId(), setting);

        UserReportBaseDto userReportBaseDto = Transform.convert(report, UserReportBaseDto.class);

        return ResponseHelp.success(userReportBaseDto);
    }

    @RequestMapping(value = "/error/paper", method = RequestMethod.GET)
    @ApiOperation(value = "获取错题组卷", notes = "获取错题组卷", httpMethod = "GET")
    public Response<PaperBaseDto> detailError(
            @RequestParam(required = true, name="id") Integer paperId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        UserPaper paper = userPaperService.get(paperId);
        if (!paper.getModule().equals(PaperModule.ERROR.key)){
            throw new ParameterException("试卷不存在");
        }
        if (!paper.getUserId().equals(user.getId())){
            throw new ParameterException("试卷不存在");
        }
        PaperBaseDto paperDto = Transform.convert(paper, PaperBaseDto.class);

        return ResponseHelp.success(paperDto);
    }

    @RequestMapping(value = "/error/start", method = RequestMethod.POST)
    @ApiOperation(value = "开始: 错题组卷", notes = "提交考试设置", httpMethod = "POST")
    public Response<UserReportBaseDto> startError(@RequestBody @Validated PreviewStartDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        JSONObject setting = new JSONObject();
        setting.put("disorder", dto.getDisorder());
        UserReportRelation report = questionFlowService.start(user.getId(), PaperModule.ERROR, dto.getPaperId(), setting);

        UserReportBaseDto userReportBaseDto = Transform.convert(report, UserReportBaseDto.class);

        return ResponseHelp.success(userReportBaseDto);
    }

    @RequestMapping(value = "/collect/paper", method = RequestMethod.GET)
    @ApiOperation(value = "获取收藏组卷", notes = "获取收藏组卷", httpMethod = "GET")
    public Response<PaperBaseDto> detailCollect(
            @RequestParam(required = true, name="id") Integer paperId
    )  {
        User user = (User) shiroHelp.getLoginUser();
        UserPaper paper = userPaperService.get(paperId);
        if (!paper.getModule().equals(PaperModule.COLLECT.key)){
            throw new ParameterException("试卷不存在");
        }
        if (!paper.getUserId().equals(user.getId())){
            throw new ParameterException("试卷不存在");
        }
        PaperBaseDto paperDto = Transform.convert(paper, PaperBaseDto.class);

        return ResponseHelp.success(paperDto);
    }

    @RequestMapping(value = "/collect/start", method = RequestMethod.POST)
    @ApiOperation(value = "开始: 收藏组卷", notes = "提交考试设置", httpMethod = "POST")
    public Response<UserReportBaseDto> startCollect(@RequestBody @Validated PreviewStartDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        JSONObject setting = new JSONObject();
        setting.put("disorder", dto.getDisorder());
        UserReportRelation report = questionFlowService.start(user.getId(), PaperModule.COLLECT, dto.getPaperId(), setting);

        UserReportBaseDto userReportBaseDto = Transform.convert(report, UserReportBaseDto.class);

        return ResponseHelp.success(userReportBaseDto);
    }

    @RequestMapping(value = "/continue", method = RequestMethod.POST)
    @ApiOperation(value = "继续做题", notes = "获取报告信息", httpMethod = "POST")
    public Response<UserReportBaseDto> continueReport(@RequestBody @Validated ReportContinueDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        UserReportRelation report = questionFlowService.continueReport(user.getId(), dto.getUserReportId());

        UserReportBaseDto userReportBaseDto = Transform.convert(report, UserReportBaseDto.class);

        return ResponseHelp.success(userReportBaseDto);
    }

    @RequestMapping(value = "/next", method = RequestMethod.POST)
    @ApiOperation(value = "获取下一题", notes = "获取下一题", httpMethod = "POST")
    public Response<UserQuestionBaseDto> next(@RequestBody @Validated ReportNextDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        UserQuestion userQuestion = questionFlowService.next(user.getId(), dto.getUserReportId());
        UserQuestionBaseDto baseDto = Transform.convert(userQuestion, UserQuestionBaseDto.class);

        // 绑定questionNos
        baseDto.setQuestionNos(Transform.convert(questionNoService.listByQuestion(userQuestion.getQuestionId()), QuestionNoExtendDto.class));

        // 绑定question
        baseDto.setQuestion(Transform.convert(questionService.get(userQuestion.getQuestionId()), QuestionExtendDto.class));

        // 绑定questionNo
        baseDto.setQuestionNo(Transform.convert(questionNoService.get(userQuestion.getQuestionNoId()), QuestionNoExtendDto.class));

        // 绑定collect
        baseDto.setCollect(userCollectQuestionService.getByUserAndQuestion(user.getId(), userQuestion.getQuestionId()) != null);

        return ResponseHelp.success(baseDto);
    }

    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    @ApiOperation(value = "提交题目答案", notes = "提交题目", httpMethod = "POST")
    public Response<Boolean> submit(@RequestBody @Validated QuestionSubmitDto dto)  {
        User user = (User) shiroHelp.getLoginUser();
        Boolean result = questionFlowService.submit(user.getId(), dto.getUserQuestionId(), dto.getTime(), dto.getAnswer());
        return ResponseHelp.success(result);
    }

    @RequestMapping(value = "/finish", method = RequestMethod.POST)
    @ApiOperation(value = "完成考试", notes = "完成考试", httpMethod = "POST")
    public Response<Boolean> finish(@RequestBody @Validated ReportFinishDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        Boolean result = questionFlowService.finish(user.getId(), dto.getUserReportId());
        return ResponseHelp.success(result);
    }

    @RequestMapping(value = "/restart", method = RequestMethod.POST)
    @ApiOperation(value = "重置考试", notes = "重置考试", httpMethod = "POST")
    public Response<Boolean> restart(@RequestBody @Validated PaperRestartDto dto)  {
        User user = (User) shiroHelp.getLoginUser();

        questionFlowService.restart(dto.getUserPaperId(), user.getId());
        return ResponseHelp.success(true);
    }
}
