package com.qmth.themis.business.templete.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.qmth.themis.business.cache.bean.ExamCacheBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.ExamStudentImportDto;
import com.qmth.themis.business.entity.TEExamActivity;
import com.qmth.themis.business.enums.ExamModeEnum;
import com.qmth.themis.business.enums.TaskStatusEnum;
import com.qmth.themis.business.service.TEExamService;
import com.qmth.themis.business.service.ThemisCacheService;
import com.qmth.themis.business.templete.TaskImportCommon;
import com.qmth.themis.business.templete.TaskImportTemplete;
import com.qmth.themis.business.templete.service.TempleteLogicService;
import com.qmth.themis.business.util.ExcelCallback;
import com.qmth.themis.business.util.ExcelError;
import com.qmth.themis.business.util.ExcelUtil;
import com.qmth.themis.business.util.JacksonUtil;
import com.qmth.themis.common.contanst.Constants;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.GsonUtil;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: 考生导入任务
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/7/15
 */
@Service
public class TaskExamStudentImportTemplete implements TaskImportTemplete {
    private final static Logger log = LoggerFactory.getLogger(TaskExamStudentImportTemplete.class);

    @Resource
    TempleteLogicService templeteLogicService;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    TEExamService teExamService;

    /**
     * 考生导入模版
     *
     * @param map
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    public Result importTask(Map<String, Object> map) throws IOException {
        log.info("importTask ossMap:{}", JacksonUtil.parseJson(map));
        TaskImportCommon taskImportCommon = new TaskImportCommon(map);
        taskImportCommon.init();
        InputStream inputStream = taskImportCommon.getUploadFileInputStream();
        taskImportCommon.setTxtList(new ArrayList());
        taskImportCommon.getTxtList().add(DateUtil.format(new Date(), Constants.DEFAULT_DATE_PATTERN) + "->开始准备处理导入的考生数据");
        Map<String, Object> finalMap = map;
        Long examId = (Long) map.get(SystemConstant.EXAM_ID);
        Map<String, TEExamActivity> teExamActivityMap = (Map<String, TEExamActivity>) map.get("teExamActivityMap");
        try {
            List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(ExamStudentImportDto.class), new ExcelCallback() {
                @Override
                public List<LinkedMultiValueMap<Integer, Object>> callback(List<LinkedMultiValueMap<Integer, Object>> finalList, List<LinkedMultiValueMap<Integer, String>> finalColumnNameList, List<LinkedMultiValueMap<Integer, ExcelError>> finalExcelErrorList) throws IllegalAccessException, IOException {
                    Map<String, String> courseCodeMap = new HashMap<>();
                    List<ExcelError> excelErrorList = new ArrayList<>();
                    if (finalExcelErrorList.size() > 0) {
                        for (int i = 0; i < finalExcelErrorList.size(); i++) {
                            excelErrorList.addAll(finalExcelErrorList.get(i).get(i));
                        }
                    }
                    for (int i = 0; i < finalList.size(); i++) {
                        LinkedMultiValueMap<Integer, Object> map = finalList.get(i);
                        List<Object> examStudentImportDtoList = map.get(i);
                        for (int y = 0; y < examStudentImportDtoList.size(); y++) {
                            ExamStudentImportDto examStudentImportDto = (ExamStudentImportDto) examStudentImportDtoList.get(y);
                            courseCodeMap.put(examStudentImportDto.getCourseCode(), examStudentImportDto.getCourseName());
                            //校验考试模式，如果是集中统一，则需填写考试场次
                            if (Objects.equals(taskImportCommon.getMode(), ExamModeEnum.TOGETHER.name())) {
                                if (Objects.nonNull(teExamActivityMap) && Objects.isNull(teExamActivityMap.get(examStudentImportDto.getExamActivityCode()))) {
                                    excelErrorList.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[场次]不存在"));
                                }
                            } else {
                                if (Objects.nonNull(examStudentImportDto.getExamActivityCode()) && SystemConstant.checkNumber(examStudentImportDto.getExamActivityCode())) {
                                    Integer code = Integer.parseInt(examStudentImportDto.getExamActivityCode());
                                    if (code > 1) {
                                        excelErrorList.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[随到随考场次不能大于1]"));
                                    }
                                }
                            }
                            excelErrorList.addAll(ExcelUtil.checkExcelField(examStudentImportDto, y, i));
                            if (Objects.nonNull(examStudentImportDto.getPassword()) && !Objects.equals(examStudentImportDto.getPassword().trim(), "")) {
                                if (examStudentImportDto.getPassword().trim().length() > 8) {
                                    excelErrorList.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[密码]长度不能大于8位"));
                                } else if (examStudentImportDto.getPassword().trim().length() < 6) {
                                    excelErrorList.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[密码]长度不能小于6位"));
                                } else {
                                    Pattern pattern = Pattern.compile(SystemConstant.PATTERN);
                                    Matcher matcher = pattern.matcher(examStudentImportDto.getPassword().trim());
                                    if (!matcher.matches()) {
                                        excelErrorList.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[密码]不能包含特殊字符，只能为字母和数字"));
                                    }
                                }
                            }
                        }
                    }
                    if (excelErrorList.size() > 0) {
                        taskImportCommon.setException(true);
                        taskImportCommon.getTbTaskHistory().setFinishTime(System.currentTimeMillis());
                        taskImportCommon.getTbTaskHistory().setProgress(0d);
                        taskImportCommon.getTbTaskHistory().setStatus(TaskStatusEnum.FINISH);
                        taskImportCommon.getTbTaskHistory().setSummary(taskImportCommon.getTxtList().toString());
                        throw new BusinessException(JSONObject.toJSONString(excelErrorList));
                    }
                    finalMap.put("courseCodeMap", courseCodeMap);
                    return finalList;
                }
            });
            //保存数据到数据库
            if (Objects.nonNull(finalList) && finalList.size() > 0) {
                log.info("开始导入考生数据");
                long start = System.currentTimeMillis();

                map = templeteLogicService.execImportExamStudentLogic(finalList, map);

                //加入更新考试列表缓存方法
                List<TEExamActivity> teExamActivityList = GsonUtil.fromJson(GsonUtil.toJson(teExamActivityMap.values()), new TypeToken<List<TEExamActivity>>() {
                }.getType());
                for (TEExamActivity t : teExamActivityList) {
                    themisCacheService.updateCurrentExamListCache(String.valueOf(examId), t.getId());
                    ExamCacheBean examCacheBean = teExamService.getExamCacheBean(examId);
                    themisCacheService.updateOrgExamListCache(examCacheBean.getOrgId().toString(), examId.toString(), t.getId());
                }
                long end = System.currentTimeMillis();
                log.info("导入考生数据结束,============耗时============:{}秒", (end - start) / 1000);
            }
        } catch (Exception e) {
            log.error("导入报错", e);
            int line = Objects.isNull(map.get("line")) ? 0 : Integer.parseInt(String.valueOf(map.get("line")));
            taskImportCommon.exception(line, e, taskImportCommon.getTxtList());
        } finally {
            if (Objects.nonNull(inputStream)) {
                inputStream.close();
            }
            //这里写入txt文件
            taskImportCommon.writeImportResultTxt(taskImportCommon.getTxtList().toString());
        }
        return ResultUtil.ok(true);
    }
}