package com.qxgmat.controller.api;

import com.github.pagehelper.Page;
import com.nuliji.tools.*;
import com.nuliji.tools.exception.AuthException;
import com.nuliji.tools.exception.ParameterException;
import com.qxgmat.data.constants.enums.QuestionSubject;
import com.qxgmat.data.constants.enums.QuestionType;
import com.qxgmat.data.constants.enums.ServiceKey;
import com.qxgmat.data.constants.enums.logic.TextbookLogic;
import com.qxgmat.data.constants.enums.module.PaperOrigin;
import com.qxgmat.data.constants.enums.status.DirectionStatus;
import com.qxgmat.data.dao.entity.*;
import com.qxgmat.data.inline.UserQuestionStat;
import com.qxgmat.data.relation.entity.TextbookQuestionRelation;
import com.qxgmat.dto.extend.UserPaperBaseExtendDto;
import com.qxgmat.dto.extend.UserReportExtendDto;
import com.qxgmat.dto.extend.UserServiceRecordExtendDto;
import com.qxgmat.dto.extend.UserTextbookGroupExtendDto;
import com.qxgmat.dto.response.UserTextbookGroupDto;
import com.qxgmat.dto.response.UserTextbookInfoDto;
import com.qxgmat.dto.response.UserTextbookPaperDto;
import com.qxgmat.help.ShiroHelp;
import com.qxgmat.service.UserPaperService;
import com.qxgmat.service.UserQuestionService;
import com.qxgmat.service.UserServiceService;
import com.qxgmat.service.UsersService;
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.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/textbook")
@Api(tags = "机经", description = "机经接口")
public class TextbookController
{
    @Autowired
    private ShiroHelp shiroHelp;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private SettingService settingService;

    @Autowired
    private UsersService usersService;

    @Autowired
    private UserPaperService userPaperService;

    @Autowired
    private UserQuestionService userQuestionService;

    @Autowired
    private UserReportService userReportService;

    @Autowired
    private UserServiceService userServiceService;

    @Autowired
    private UserOrderRecordService userOrderRecordService;

    @Autowired
    private QuestionFlowService questionFlowService;

    @Autowired
    private TextbookPaperService textbookPaperService;

    @Autowired
    private TextbookQuestionService textbookQuestionService;

    @Autowired
    private TextbookLibraryService textbookLibraryService;

    @Autowired
    private TextbookLibraryHistoryService textbookLibraryHistoryService;

    @Autowired
    private TextbookTopicService textbookTopicService;

    @RequestMapping(value = "/progress", method = RequestMethod.GET)
    @ApiOperation(value = "机经进度", httpMethod = "GET")
    public Response<List<UserTextbookGroupDto>> progress(HttpSession session) {
        User user = (User) shiroHelp.getLoginUser();

        TextbookLibrary latest = textbookLibraryService.getLatest();
        TextbookLibrary second = textbookLibraryService.getSecond();
        List<UserTextbookGroupDto> p = new ArrayList<>(2);

        for(TextbookLibrary library : new ArrayList<TextbookLibrary>(2){{add(latest);add(second);}}){
            UserTextbookGroupDto dto = Transform.convert(library, UserTextbookGroupDto.class);
            dto.setIsLatest(library.getEndDate() == null ? 1 : 0);
            dto.setNeedService(library.getEndDate() == null);
            dto.setHasService(true);
            // 获取第三层所有题目,并获取题目统计
            List<TextbookQuestion> list = textbookQuestionService.listByLibrary(library.getId());
            List<TextbookQuestionRelation> relations = textbookQuestionService.relation(list);
            dto.setStat(textbookQuestionService.statPaper(list));
            dto.setQuestionNumber(list.size());
            Map<Object, UserQuestionStat> userQuestionStatMap = null;
            if(user != null){
                if (dto.getNeedService()){
                    dto.setHasService(userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK));
                    // 服务, 判断对应服务状态
                    UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK);
                    dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class));
                }
                Collection questionNoIds = Transform.getIds(list, QuestionNo.class, "id");
                List<UserQuestion> userQuestionList = userQuestionService.listByQuestionNo(user.getId(), questionNoIds);
                userQuestionStatMap = userQuestionService.statQuestionNoMap(userQuestionList);

                dto.setUserStat(userQuestionService.statQuestion(userQuestionList));

                if (list.size() > userQuestionStatMap.size()){
                    dto.setUserNumber(userQuestionStatMap.size());
                    dto.setMinTimes(0);
                }else{
                    int minTimes = 0;
                    // 统计最小轮的已做题数
                    for(UserQuestionStat stat : userQuestionStatMap.values()){
                        if(stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
                    }
                    int userNumber = 0;
                    for(UserQuestionStat stat : userQuestionStatMap.values()){
                        if(stat.getUserNumber() > minTimes) userNumber += 1;
                    }
                    dto.setMinTimes(minTimes);
                    dto.setUserNumber(userNumber);
                }
            }

            List<UserTextbookGroupExtendDto> childrenDtos = new ArrayList<>(TextbookLogic.all().length);
            for(TextbookLogic logic : TextbookLogic.all()){
                UserTextbookGroupExtendDto extendDto = new UserTextbookGroupExtendDto();
                extendDto.setLogic(logic.key);
                extendDto.setTitle(logic.key.toUpperCase());
                List<TextbookQuestionRelation> childQuestionList = relations.stream().filter((q)-> logic.contain(QuestionType.ValueOf(q.getQuestion().getQuestionType()))).collect(Collectors.toList());
                extendDto.setQuestionNumber(childQuestionList.size());
                if (user != null){
                    int minTimes = 0;
                    int userQuestionNumber = 0;
                    boolean flag = true;
                    for(TextbookQuestion questionNo : childQuestionList){
                        UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
                        if (stat == null) {
                            flag = false;
                            break;
                        }
                        if (stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
                    }
                    if (!flag) minTimes = 0;
                    for(TextbookQuestion questionNo : childQuestionList){
                        UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
                        if (stat != null && stat.getUserNumber() > minTimes)  userQuestionNumber += 1;
                    }
                    extendDto.setUserNumber(userQuestionNumber);
                    extendDto.setMinTimes(minTimes);
                }
                childrenDtos.add(extendDto);
            }
            dto.setChildren(childrenDtos);
            p.add(dto);
        }

        return ResponseHelp.success(p);
    }

    @RequestMapping(value = "/info", method = RequestMethod.GET)
    @ApiOperation(value = "机经信息", httpMethod = "GET")
    public Response<UserTextbookInfoDto> info(HttpSession session) {
        User user = (User) shiroHelp.getLoginUser();
        UserTextbookInfoDto dto = new UserTextbookInfoDto();

        TextbookLibrary latest = textbookLibraryService.getLatest();
        dto.setLatest(latest);
        if (user != null){
            dto.setHasService(userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK));
            UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK);
            dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class));
        }
        TextbookLibrary second = textbookLibraryService.getSecond();
        dto.setSecond(second);

        return ResponseHelp.success(dto);
    }

    @RequestMapping(value = "/year", method = RequestMethod.GET)
    @ApiOperation(value = "机经年度更新信息", httpMethod = "GET")
    public Response<List<TextbookLibrary>> year(
            @RequestParam(required = false) String year,
            HttpSession session) {
        Date start;
        try {
            start = DateFormat.getDateInstance().parse(String.format("%s-01-01", year));
        } catch (ParseException e) {
            throw new ParameterException("日期格式错误");
        }
        Date end = Tools.addYear(start, 1);
        List<TextbookLibrary> libraryList = textbookLibraryService.listByTime(start, end);

        return ResponseHelp.success(libraryList);
    }

    @RequestMapping(value = "/history/all", method = RequestMethod.GET)
    @ApiOperation(value = "机经更新记录", httpMethod = "GET")
    public Response<List<TextbookLibraryHistory>> listHistory(
            @RequestParam(required = true) String subject,
            HttpSession session) {
        User user = (User) shiroHelp.getLoginUser();
        if (user == null){
            throw new AuthException("请先登录");
        }
        if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
            throw new ParameterException("没有机经查看权限");
        }
        if (QuestionSubject.ValueOf(subject) == null){
            throw new ParameterException("科目错误");
        }
        TextbookLibrary library = textbookLibraryService.getLatest();
        List<TextbookLibraryHistory> p = textbookLibraryHistoryService.allByLibraryAndSubject(library.getId(), QuestionSubject.ValueOf(subject));

        return ResponseHelp.success(p);
    }

    @RequestMapping(value = "/topic/list", method = RequestMethod.GET)
    @ApiOperation(value = "机经列表", httpMethod = "GET")
    public Response<PageMessage<TextbookTopic>> listTopic(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) boolean latest,
            @RequestParam(required = true) String subject,
            @RequestParam(required = false) String[] qualitys,
            @RequestParam(required = false) Boolean isOld,
            @RequestParam(required = false, defaultValue = "id") String order,
            @RequestParam(required = false, defaultValue = "desc") String direction,
            HttpSession session) {
        TextbookLibrary library;
        if (latest){
            User user = (User) shiroHelp.getLoginUser();
            if (user == null){
                throw new AuthException("请先登录");
            }
            if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
                throw new ParameterException("没有机经查看权限");
            }
            library = textbookLibraryService.getLatest();
        }else{
            // 获取往期:倒数第二
            library = textbookLibraryService.getSecond();
        }

        Page<TextbookTopic> p = textbookTopicService.list(page, size, library.getId(), QuestionSubject.ValueOf(subject), qualitys, isOld, order, DirectionStatus.ValueOf(direction));

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


    @RequestMapping(value = "/paper/list", method = RequestMethod.GET)
    @ApiOperation(value = "机经组卷列表", httpMethod = "GET")
    public Response<List<UserTextbookPaperDto>> listPaper(
            @RequestParam(required = false, defaultValue = "1") int page,
            @RequestParam(required = false, defaultValue = "100") int size,
            @RequestParam(required = true) boolean latest,
            @RequestParam(required = true) String logic,
            @RequestParam(required = false)  Integer times,
            HttpSession session) {
        User user = (User) shiroHelp.getLoginUser();
        TextbookLibrary library;
        if (latest){
            if (user == null){
                throw new AuthException("请先登录");
            }
            if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
                throw new ParameterException("没有机经查看权限");
            }
            library = textbookLibraryService.getLatest();
        }else{
            // 获取往期:倒数第二
            library = textbookLibraryService.getSecond();
        }
        List<TextbookPaper> p = textbookPaperService.list(page, size, library.getId(), user != null ? user.getId():null, TextbookLogic.ValueOf(logic), times);
        List<UserTextbookPaperDto> pr = Transform.convert(p, UserTextbookPaperDto.class);

        // 获取试卷统计信息
        Map<Integer, Integer[]> questionNoIdsMap = new HashMap<>();
        for(TextbookPaper paper : p){
            questionNoIdsMap.put(paper.getId(), paper.getQuestionNoIds());
        }
        Map statMap = textbookQuestionService.statPaperMap(questionNoIdsMap);
        Transform.combine(pr, statMap, UserTextbookPaperDto.class, "id", "stat");

        if (user != null){
            // 获取做题记录
            Collection ids = Transform.getIds(p, TextbookPaper.class, "id");
            List<UserPaper> userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.TEXTBOOK, ids, null);
            Transform.combine(pr, userPaperList, UserTextbookPaperDto.class, "id", "paper", UserPaper.class, "originId", UserPaperBaseExtendDto.class);
            // 绑定userPaperId,用于关联report
            Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id");
            Transform.combine(pr, userPaperMap, UserTextbookPaperDto.class, "id", "userPaperId");

            // 获取最后一次作业结果
            Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
            List<UserReport> reportList = userReportService.listWithLater(paperIds);
            Transform.combine(pr, reportList, UserTextbookPaperDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class);
        }

        return ResponseHelp.success(pr);
    }
}