package cn.com.qmth.examcloud.tool.service.create_random_paper_template;

import cn.com.qmth.examcloud.tool.cache.LoginSessionManager;
import cn.com.qmth.examcloud.tool.config.SysProperty;
import cn.com.qmth.examcloud.tool.entity.TaskEntity;
import cn.com.qmth.examcloud.tool.service.CommonService;
import cn.com.qmth.examcloud.tool.service.create_random_paper_template.vo.PaperStructVO;
import cn.com.qmth.examcloud.tool.service.create_random_paper_template.vo.PaperVO;
import cn.com.qmth.examcloud.tool.service.create_random_paper_template.vo.RandomPaperTemplateVO;
import cn.com.qmth.examcloud.tool.service.export_student_answer_and_score_detail.vo.CourseVO;
import cn.com.qmth.examcloud.tool.utils.HttpHelper;
import cn.com.qmth.examcloud.tool.utils.JsonMapper;
import cn.com.qmth.examcloud.tool.utils.StatusException;
import cn.com.qmth.examcloud.tool.vo.Pager;
import cn.com.qmth.examcloud.tool.vo.user.User;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class CreateRandomPaperTemplateTask {

    private final static Logger log = LoggerFactory.getLogger(CreateRandomPaperTemplateTask.class);

    @Autowired
    private CommonService commonService;

    @Autowired
    private SysProperty sysProperty;

    public void start(TaskEntity task) {
        JsonNode jsonParams = new JsonMapper().getNode(task.getParams());
        if (jsonParams == null) {
            throw new StatusException("任务参数解析错误！");
        }

        User user = LoginSessionManager.getLoginSession(task.getUserToken());
        if (user == null) {
            throw new StatusException("用户未登录！");
        }

        this.execute(user, jsonParams, task);
    }

    private void execute(User user, JsonNode jsonParams, TaskEntity task) {
        Long examId = jsonParams.get("examId").asLong(0L);
        String questionPool = jsonParams.get("questionPool").asInt(1) == 1 ? "IMPORT" : "GENERATE";
        String structType = jsonParams.get("structType").asInt(1) == 1 ? "EXACT" : "BLUEPRINT";
        String structName = jsonParams.get("structName").asText("");
        String paperKeywords = jsonParams.get("paperKeywords").asText("");

        log.info("examId:{} questionPool:{} structType:{} structName:{} paperKeywords:{}", examId, questionPool,
                structType, structName, paperKeywords);

        List<CourseVO> courses = commonService.getExamCourseList(user, examId);
        log.info("待处理课程总数为:{} examId:{}", courses.size(), examId);

        if (courses.isEmpty()) {
            return;
        }

        int index = 0;
        List<String> messages = new ArrayList<>();

        for (CourseVO course : courses) {
            // 按考试课程逐个处理
            index++;

            if (this.existRandomPaperTemplate(user, course.getCourseId())) {
                String msg = String.format("【%s】 课程代码：%s 已存在随机抽卷模板！", index, course.getCourseCode());
                messages.add(msg);
                log.warn(msg);
                continue;
            }

            // 获取试卷结构
            String paperStructId = this.getPaperStructId(user, course.getCourseCode(), structType, structName);
            if (paperStructId == null) {
                String msg = String.format("【%s】 课程代码：%s 未找到试卷结构！", index, course.getCourseCode());
                messages.add(msg);
                log.warn(msg);
                continue;
            }

            // 获取试卷列表
            List<String> paperIds = this.getPapers(user, course.getCourseCode(), questionPool, paperKeywords);
            if (paperIds.isEmpty()) {
                String msg = String.format("【%s】 课程代码：%s 未找到相关试卷！", index, course.getCourseCode());
                messages.add(msg);
                log.warn(msg);
                continue;
            }

            // 保存随机抽卷模板
            try {
                this.saveRandomPaperTemplate(user, course, structType, paperStructId, questionPool, paperIds);
            } catch (Exception e) {
                String msg = String.format("【%s】 课程代码：%s 处理失败！%s", index, course.getCourseCode(),
                        e.getMessage());
                messages.add(msg);
                log.warn(msg);
                continue;
            }

            String msg = String.format("【%s】 课程代码：%s 处理完成！", index, course.getCourseCode());
            log.info(msg);
        }

        task.setDescription(StringUtils.join(messages, "\n"));
    }

    /**
     * 获取试卷结构信息
     */
    private String getPaperStructId(User user, String courseCode, String structType, String structName) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", user.getKey());
        headers.put("token", user.getToken());

        Map<String, String> params = new HashMap<>();
        params.put("courseNo", courseCode);
        params.put("type", structType);

        String url = user.getServerUrl() + "/api/ecs_ques/paperStruct";
        String json = HttpHelper.get(url, headers, params);

        JsonMapper jsonMapper = new JsonMapper();
        List<PaperStructVO> list = jsonMapper.toList(json, PaperStructVO.class);
        for (PaperStructVO vo : list) {
            log.info("courseCode:{} paperStructId:{} structName:{}", courseCode, vo.getId(), vo.getName());
            if (vo.getName().equals(structName)) {
                return vo.getId();
            }
        }

        return null;
    }

    /**
     * 判断课程是否已存在随机抽卷模板
     */
    private boolean existRandomPaperTemplate(User user, Long courseId) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", user.getKey());
        headers.put("token", user.getToken());

        String url = user.getServerUrl() + "/api/ecs_ques/randompaper/page?pageSize=1&courseId=" + courseId;
        String json = HttpHelper.post(url, headers, null);

        JsonMapper jsonMapper = new JsonMapper();
        Pager<RandomPaperTemplateVO> page = jsonMapper.parseJson(json,
                new TypeReference<Pager<RandomPaperTemplateVO>>() {

                });

        return !page.getContent().isEmpty();
    }

    /**
     * 获取试卷列表
     */
    private List<String> getPapers(User user, String courseCode, String questionPool, String paperKeywords) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", user.getKey());
        headers.put("token", user.getToken());

        Map<String, String> params = new HashMap<>();
        params.put("courseNo", courseCode);
        params.put("ids", "");

        int pageNo = 0, pageSize = 100, total = 0;

        String url;
        if ("IMPORT".equals(questionPool)) {
            url = user.getServerUrl() + "/api/ecs_ques/importPaper/huoge/%s/" + pageSize;
        } else {
            url = user.getServerUrl() + "/api/ecs_ques/genPaper/huoge/%s/" + pageSize;
        }

        List<String> paperIds = new ArrayList<>();
        JsonMapper jsonMapper = new JsonMapper();
        String[] keywords = paperKeywords.split(",");

        while (true) {
            pageNo++;

            String json = HttpHelper.get(String.format(url, pageNo), headers, params);
            Pager<PaperVO> page = jsonMapper.parseJson(json, new TypeReference<Pager<PaperVO>>() {

            });

            if (page == null || CollectionUtils.isEmpty(page.getContent())) {
                break;
            }

            total += page.getContent().size();
            float rate = total * 100f / page.getTotalElements();
            log.info("courseCode:{} 已获取试卷数:{} 进度:{}%", courseCode, total, rate);

            for (PaperVO vo : page.getContent()) {
                boolean match = false;
                for (String keyword : keywords) {
                    if (vo.getName().contains(keyword)) {
                        match = true;
                        break;
                    }
                }

                if (match) {
                    paperIds.add(vo.getId());
                }
                log.info("【{}】courseCode:{} paperId:{} paperName:{}", match ? "匹配" : "忽略", courseCode, vo.getId(),
                        vo.getName());
            }
        }

        return paperIds;
    }

    /**
     * 保存随机抽卷模板
     */
    public void saveRandomPaperTemplate(User user, CourseVO course, String paperStructType, String paperStructId,
            String paperType, List<String> paperIds) {
        Map<String, String> headers = new HashMap<>();
        headers.put("key", user.getKey());
        headers.put("token", user.getToken());

        Map<String, String> params = new HashMap<>();
        params.put("name", course.getCourseName() + "-模板");//todo
        params.put("courseId", String.valueOf(course.getCourseId()));
        params.put("paperStructType", paperStructType);
        params.put("paperStructId", paperStructId);
        params.put("paperType", paperType);
        params.put("paperIds", StringUtils.join(paperIds, ","));

        final String url = user.getServerUrl() + "/api/ecs_ques/randompaper/save?" + HttpHelper.toUrlParams(params);
        HttpHelper.post(url, headers, null);
    }

}
