package com.qxgmat.service;

import com.github.pagehelper.Page;
import com.nuliji.tools.AbstractService;
import com.nuliji.tools.PageResult;
import com.nuliji.tools.Transform;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.nuliji.tools.mybatis.Example;
import com.qxgmat.data.constants.enums.SettingKey;
import com.qxgmat.data.constants.enums.module.PaperModule;
import com.qxgmat.data.constants.enums.status.HomeworkPreviewStatus;
import com.qxgmat.data.dao.HomeworkPreviewMapper;
import com.qxgmat.data.dao.entity.HomeworkPreview;
import com.qxgmat.data.dao.entity.UserPaper;
import com.qxgmat.data.dao.entity.UserReport;
import com.qxgmat.data.relation.UserPaperRelationMapper;
import com.qxgmat.data.relation.UserReportRelationMapper;
import com.qxgmat.data.relation.entity.QuestionNoRelation;
import com.qxgmat.data.relation.entity.UserHomeworkPreviewRelation;
import com.qxgmat.service.extend.ToolsService;
import com.qxgmat.service.inline.QuestionNoService;
import com.qxgmat.service.inline.UserReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class HomeworkPreviewService extends AbstractService {
    private static final Logger logger = LoggerFactory.getLogger(HomeworkPreviewService.class);

    @Resource
    private HomeworkPreviewMapper homeworkPreviewMapper;

    @Resource
    private QuestionNoService questionNoService;

    @Resource
    private UserReportService userReportService;

    @Resource
    private UserPaperService userPaperService;

    @Resource
    private UserReportRelationMapper userReportRelationMapper;

    @Resource
    private UserPaperRelationMapper userPaperRelationMapper;

    @Resource
    private ToolsService toolsService;

    // 完成一次
    public boolean finished(UserPaper userPaper){

        return true;
    }

    /**
     * 查找用户作业，并关联用户完成度最高的最后一次
     * @param page
     * @param size
     * @param category
     * @param userId
     * @param previewId
     * @param startTime
     * @param endTime
     * @return
     */
    public PageResult<UserHomeworkPreviewRelation> listAdmin(int page, int size, Number category, Number userId, Number previewId, String startTime, String endTime){
        Page<UserPaper> p = page(() -> {
            userPaperRelationMapper.listHomeworkPreviewAdmin(category, userId, previewId, startTime, endTime);
        }, page, size);

        Collection ids = Transform.getIds(p, UserPaper.class, "id");

        // 获取详细数据
        List<UserPaper> list = userPaperService.select(ids);
        List<UserHomeworkPreviewRelation> pr = Transform.convert(list, UserHomeworkPreviewRelation.class);

        // 获取完成度最高的作业结果
        List<UserReport> reportList = userReportRelationMapper.listFinishLast(ids, startTime, endTime);
        Collection reportIds = Transform.getIds(reportList, UserReport.class, "id");
        Transform.replace(reportList, userReportService.select(reportIds), UserReport.class, "id");

        Transform.combine(p, reportList, UserHomeworkPreviewRelation.class, "id", "report", UserReport.class, "paperId");

        return new PageResult<>(pr, p.getTotal());
    }

    /**
     * 查找用户作业, 并关联用户最后一次作业
     * @param page
     * @param size
     * @param category
     * @param userId
     * @param endTime
     * @param finish
     * @return
     */
    public PageResult<UserHomeworkPreviewRelation> list(int page, int size, Number category, Number userId, String endTime, Boolean finish){
        Page<UserPaper> p = page(()->{
            userPaperRelationMapper.listHomeworkPreview(category, userId, endTime, finish);
        },page, size);

        Collection ids = Transform.getIds(p, UserPaper.class, "id");

        // 获取详细数据
        List<UserPaper> list = userPaperService.select(ids);
        List<UserHomeworkPreviewRelation> pr = Transform.convert(list, UserHomeworkPreviewRelation.class);

        // 获取最后一次作业结果
        List<UserReport> reportList = userReportRelationMapper.listLast(ids);
        Collection reportIds = Transform.getIds(reportList, UserReport.class, "id");
        Transform.replace(reportList, userReportService.select(reportIds), UserReport.class, "id");

        Transform.combine(p, reportList, UserHomeworkPreviewRelation.class, "id", "report", UserReport.class, "paperId");

        return new PageResult<>(pr, p.getTotal());
    }

    /**
     * 获取用户分组作业列表，并关联用户最后一次作业
     * @param userId
     * @param top
     * @return
     */
    public Map<Object, Collection<UserHomeworkPreviewRelation>> groupByCategory(Number userId, Number top){
        List<UserPaper> p = userPaperRelationMapper.listHomeworkPreviewGroupTop(userId, top);
        Map<Object, Collection<UserHomeworkPreviewRelation>> relationMap = new HashMap<>();

        if(p.size() == 0) return relationMap;

        Collection ids = Transform.getIds(p, UserPaper.class, "id");

        // 获取详细数据
        List<UserPaper> list = userPaperService.select(ids);
        List<UserHomeworkPreviewRelation> pr = Transform.convert(list, UserHomeworkPreviewRelation.class);

        // 获取最后一次作业结果
        List<UserReport> reportList = userReportRelationMapper.listLast(ids);
        Collection reportIds = Transform.getIds(reportList, UserReport.class, "id");
        Transform.replace(reportList, userReportService.select(reportIds), UserReport.class, "id");

        Transform.combine(pr, reportList, UserHomeworkPreviewRelation.class, "id", "report", UserReport.class, "paperId");

        for(UserHomeworkPreviewRelation row: pr){
            List<UserHomeworkPreviewRelation> l;
            Number moduleId = row.getModuleId();
            if(!relationMap.containsKey(moduleId)){
                l = new ArrayList<>();
                relationMap.put(moduleId, l);
            }else{
                l = (List<UserHomeworkPreviewRelation>)relationMap.get(moduleId);
            }
            l.add(row);
        }
        return relationMap;
    }

    /**
     * 完成预习作业
     * @param report
     */
    public void Finish(UserReport report){

    }

    @Transactional
    public HomeworkPreview add(HomeworkPreview homeworkPreview){
        int result = insert(homeworkPreviewMapper, homeworkPreview);
        homeworkPreview = one(homeworkPreviewMapper, homeworkPreview.getId());
        if(homeworkPreview == null){
            throw new SystemException("预习作业添加失败");
        }
        Integer[] userIds = homeworkPreview.getUserIds();

        // 获取考题时间
        List<QuestionNoRelation> relationList = questionNoService.listWithRelationByIds(homeworkPreview.getQuestionNoIds());
        Integer time = toolsService.computerTime(SettingKey.EXERCISE_TIME, relationList);
        for(Integer userId : userIds){
            userPaperService.add(UserPaper.builder()
                    .module(PaperModule.HOMEWORK_PREVIEW.key)
                    .userId(userId)
                    .title(homeworkPreview.getTitle())
                    .moduleId(homeworkPreview.getId())
                    .questionNoIds(homeworkPreview.getQuestionNoIds())
                    .time(time)
                    .build()
            );
        }
        return homeworkPreview;
    }

    @Transactional
    public HomeworkPreview edit(HomeworkPreview homeworkPreview){
        HomeworkPreview in = one(homeworkPreviewMapper, homeworkPreview.getId());
        if(in == null){
            throw new ParameterException("预习作业不存在");
        }
        int result = update(homeworkPreviewMapper, homeworkPreview);

        List<Integer> oldList = Arrays.stream(in.getUserIds()).collect(Collectors.toList());
        List<Integer> newList = Arrays.stream(homeworkPreview.getUserIds()).collect(Collectors.toList());

        // 移除旧用户试卷
        oldList.removeAll(newList);
        userPaperService.removeByUsersAndPaper(oldList, PaperModule.HOMEWORK_PREVIEW, homeworkPreview.getId());

        // 获取旧用户做为编辑试卷
        List<Integer> editList = Arrays.stream(in.getUserIds()).collect(Collectors.toList());
        editList.removeAll(oldList);

        // 获取考题时间
        List<QuestionNoRelation> relationList = questionNoService.listWithRelationByIds(homeworkPreview.getQuestionNoIds());
        Integer time = toolsService.computerTime(SettingKey.EXERCISE_TIME, relationList);
        for(Integer userId : newList){
            if (!editList.contains(userId)){
                // 添加
                userPaperService.add(UserPaper.builder()
                        .module(PaperModule.HOMEWORK_PREVIEW.key)
                        .userId(userId)
                        .title(homeworkPreview.getTitle())
                        .moduleId(homeworkPreview.getId())
                        .questionNoIds(homeworkPreview.getQuestionNoIds())
                        .time(time)
                        .build()
                );
                editList.remove(userId);
            }
        }
        // 修改
        userPaperService.editByUsersAndPaper(UserPaper.builder()
                .title(homeworkPreview.getTitle())
                .questionNoIds(homeworkPreview.getQuestionNoIds())
                .time(time)
                .build(),
                oldList,
                PaperModule.HOMEWORK_PREVIEW, homeworkPreview.getId());

        return homeworkPreview;
    }

    public boolean delete(Number id){
        HomeworkPreview in = one(homeworkPreviewMapper, id);
        if(in == null){
            throw new ParameterException("预习作业不存在");
        }
        int result = delete(homeworkPreviewMapper, id);
        return result > 0;
    }

    public HomeworkPreview get(Number id){
        HomeworkPreview in = one(homeworkPreviewMapper, id);

        if(in == null){
            throw new ParameterException("预习作业不存在");
        }
        return in;
    }

    public Page<HomeworkPreview> select(int page, int pageSize){
        return select(homeworkPreviewMapper, page, pageSize);
    }

    public Page<HomeworkPreview> select(int page, int pageSize, Integer category, HomeworkPreviewStatus status){
        Example example = new Example(HomeworkPreview.class);
        if(category != null && category>0)
            example.and(
                    example.createCriteria().andEqualTo("category", category)
            );
        if (status!=HomeworkPreviewStatus.ALL){
            tk.mybatis.mapper.entity.Example.Criteria criteria = example.createCriteria();
            switch(status){
                case NO_START:
                    criteria.andLessThan("startTime", new Date());
                    break;
                case PROCESS:
                    criteria.andGreaterThanOrEqualTo("startTime", new Date()).andLessThan("endTime", new Date());
                    break;
                case FINISH:
                    criteria.andGreaterThanOrEqualTo("endTime", new Date());
                    break;
            }
            example.and(criteria);
        }
        example.orderBy("id").desc();
        return select(homeworkPreviewMapper, example, page, pageSize);
    }

    public List<HomeworkPreview> select(Collection ids){
        return select(homeworkPreviewMapper, ids);
    }

}
