/**
 * Copyright (C), 2015-2018, XXX有限公司
 * FileName: LibrarySubjectImport
 * Author:   phone
 * Date:     2018/6/8 14:37
 * Description: 题库试题导入
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yizhi.application.exam.controller;

import cn.hutool.json.JSONUtil;
import com.yizhi.core.application.context.TaskContext;
import com.yizhi.core.application.file.task.AbstractDefaultTask;
import com.yizhi.exam.application.feign.QuestionLibrarySubjectClient;
import com.yizhi.exam.application.vo.TrQuestionLibrarySubjectVO;
import com.yizhi.exam.application.vo.TrQuestionSubjectOptionVO;
import com.yizhi.exam.application.vo.domain.QuestionLibrary;
import com.yizhi.exam.application.vo.domain.TrExamQuestion;
import com.yizhi.exam.application.vo.infile.ImportExamQuestionSubjectVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 〈一句话功能简述〉<br>
 * 〈题库试题导入〉
 *
 * @author phone
 * @create 2018/6/8
 * @since 1.0.0
 */
@Component
public class LibrarySubjectImport extends AbstractDefaultTask<List<ImportExamQuestionSubjectVO>, Map<String, Object>> {

    private static String BASEPATH = "e:/";
    private String XLSX = ".xlsx";
    private String TASKNAME = "题库试题导入";

    private static Logger LOGGER = LoggerFactory.getLogger(LibrarySubjectImport.class);
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-hh HH:mm:ss");

    @Autowired
    QuestionLibrarySubjectClient questionLibrarySubjectClient;

    //@Override
    public List<ImportExamQuestionSubjectVO> execute(Map<String, Object> map) {
        QuestionLibrary questionLibrary;
        TrQuestionLibrarySubjectVO trQuestionLibrarySubjectVO = null;
        List<TrQuestionLibrarySubjectVO> insertList = new ArrayList<>();
        List<TrQuestionSubjectOptionVO> trQuestionSubjectOptionVOList;
        TrQuestionSubjectOptionVO trQuestionSubjectOptionVO;
        TrExamQuestion trExamQuestion;
        String url = (String) map.get("url");
        Long libraryId = (Long) map.get("libraryId");
        Long companyId = (Long) map.get("companyId");
        Long accountId = (Long) map.get("accountId");
        String accountName = (String) map.get("accountName");
        Long siteId = (Long) map.get("siteId");
        Long orgId = (Long) map.get("orgId");
        int type = 0;

        LOGGER.info("题库导入入参map:{}", JSONUtil.toJsonStr(map));
        Date time = new Date();
        Workbook book = getFile(url);
        Long id = System.currentTimeMillis();
        TaskContext taskContext = new TaskContext(id, "QUESTION-IMPORT" + id, TASKNAME, accountId, time, siteId, companyId);
       // working(taskContext);
        List<ImportExamQuestionSubjectVO> list = readExcelFile(book, taskContext);
        LOGGER.info("题库导入入参内容:{}", JSONUtil.toJsonStr(list));
        int sort = 1;        //生成默认排序
        int s = 1;
        int success = 0;
        int fail = 0;
        List<Integer> rightAnswerErrorList = new ArrayList<>();
        List<Integer> optionErrorList = new ArrayList<>();
        List<Integer> typeErrorList = new ArrayList<>();
        for (ImportExamQuestionSubjectVO importExamQuestionSubjectVO : list) {
            trQuestionLibrarySubjectVO = new TrQuestionLibrarySubjectVO();
            trQuestionLibrarySubjectVO.setCompanyId(companyId);
            trQuestionLibrarySubjectVO.setSiteId(siteId);
            trQuestionLibrarySubjectVO.setOrgId(orgId);
            trQuestionLibrarySubjectVO.setAccountId(accountId);
            trQuestionLibrarySubjectVO.setAccountName(accountName);
            sort += 1;
            try {
                String typeString = importExamQuestionSubjectVO.getType();
                if (typeString.equals("单选题")) {
                    type = 1;
                } else if (typeString.equals("多选题")) {
                    type = 2;
                } else if (typeString.equals("判断题")) {
                    type = 3;
                } else if (typeString.equals("问答题")) {
                    type = 4;
                } else {
                    fail++;
                    typeErrorList.add(sort);
                    //taskDetail(id, "第" + sort + "行试题类型不正确");
                    LOGGER.error("第{}行试题类型不正确", sort);
                    continue;
                }
                if (type > 0 && type <= 4) {
                    trQuestionLibrarySubjectVO.setType(type);
                }
                trQuestionLibrarySubjectVO.setQuestionLabel(importExamQuestionSubjectVO.getQuestionLabel() == null ? "" : importExamQuestionSubjectVO.getQuestionLabel());
                trQuestionLibrarySubjectVO.setStem(importExamQuestionSubjectVO.getStem() == null ? "" : importExamQuestionSubjectVO.getStem());
                trQuestionLibrarySubjectVO.setAnalysis(importExamQuestionSubjectVO.getAnalysis() == null ? "" : importExamQuestionSubjectVO.getAnalysis());
                trQuestionLibrarySubjectVO.setLibraryId(libraryId);
                if (type == 4) {
                    trQuestionLibrarySubjectVO.setScoreRule(importExamQuestionSubjectVO.getIsAnswer() == null ? "" : importExamQuestionSubjectVO.getIsAnswer());
                }

                int rightAnswerNum = 0;
                if (StringUtils.isNotBlank(importExamQuestionSubjectVO.getIsAnswer())) {
                    String a = importExamQuestionSubjectVO.getIsAnswer();
//                    for (int i = 0; i < a.length(); i++) {
//                        if (a.charAt(i) == ',' || a.charAt(i) == '，' || a.charAt(i) == '.' || a.charAt(i) == '0') {
//                            continue;
//                        } else {
//                            rightAnswerNum++;
//                        }
//                    }
                    List<String> answerList = Arrays.asList(importExamQuestionSubjectVO.getIsAnswer().split(","));
                    if (CollectionUtils.isNotEmpty(answerList)){
                        rightAnswerNum = answerList.size();
                    }
                }
                List<String> options = importExamQuestionSubjectVO.getOption();
                if (null != options && options.size() > 0) {
                    if (type == 1) {
                        if (rightAnswerNum != 1) {
                            fail++;
                            rightAnswerErrorList.add(sort);
                            //taskDetail(id, "第" + sort + "行正确答案数不正确");
                            LOGGER.error("第{}行正确答案数不正确", sort);
                        }
                    }
                    if (type == 2) {
                        if (rightAnswerNum <= 1 || rightAnswerNum > options.size()) {
                            fail++;
                            rightAnswerErrorList.add(sort);
//                            taskDetail(id, "第" + sort + "行正确答案数不正确");
                            LOGGER.error("第{}行正确答案数不正确", sort);
                        }
                    }
                    if (type == 3) {
                        if (rightAnswerNum != 1) {
                            fail++;
                            rightAnswerErrorList.add(sort);
//                            taskDetail(id, "第" + sort + "行正确答案数不正确");
                            LOGGER.error("第{}行正确答案数不正确", sort);
                        }
                    }
                    int index = 1;
                    if (options.size() < 2) {
                        fail++;
                        optionErrorList.add(sort);
//                        taskDetail(id, "第" + sort + "行试题选项个数不正确");
                        LOGGER.error("第{}行试题选项个数不正确", sort);
                        continue;
                    }

                    trQuestionSubjectOptionVOList = new ArrayList<TrQuestionSubjectOptionVO>();
                    LOGGER.info("***********************rightAnswerNum:" + rightAnswerNum);
                    Boolean hasRightAnswer = false;
                    for (String option : options) {
                        trQuestionSubjectOptionVO = new TrQuestionSubjectOptionVO();
                        if (StringUtils.isBlank(option)) {
                            continue;
                        }
                        trQuestionSubjectOptionVO.setContent(option.trim());
                        if (null != importExamQuestionSubjectVO.getIsAnswer()) {
                            List<String> answerList = Arrays.asList(importExamQuestionSubjectVO.getIsAnswer().split(","));
                            if (answerList.contains(String.valueOf(index))) {
                                trQuestionSubjectOptionVO.setIsAnswer(1);
                                hasRightAnswer = true;
                            } else {
                                trQuestionSubjectOptionVO.setIsAnswer(0);
                            }
                        }
//                        if (null != importExamQuestionSubjectVO.getIsAnswer() && importExamQuestionSubjectVO.getIsAnswer().contains(index + "")) {
//                            //是正确答案
//                            trQuestionSubjectOptionVO.setIsAnswer(1);
//                        } else {
//                            trQuestionSubjectOptionVO.setIsAnswer(0);
//                        }
                        trQuestionSubjectOptionVO.setSort(index);
                        trQuestionSubjectOptionVOList.add(trQuestionSubjectOptionVO);
                        index++;
                    }
                    if (!hasRightAnswer) {
                        rightAnswerErrorList.add(sort);
                        //taskDetail(id, "第" + sort + "行正确答案数不正确");
                        LOGGER.error("第{}行正确答案数不正确", sort);
                    }
                    trQuestionLibrarySubjectVO.setTrQuestionSubjectOptionVOList(trQuestionSubjectOptionVOList);
                }
                insertList.add(trQuestionLibrarySubjectVO);
//                Long resultId = questionLibrarySubjectClient.insert(trQuestionLibrarySubjectVO);
//                if (null == resultId || resultId < 1) {
//                    fail(taskContext, "试题保存过程中出现错误");
//                }
//                taskDetail(taskContext.getTaskId(), TASKNAME + "导入数据第" + s + "行成功");
                s++;
                success++;
            } catch (Exception e) {
                e.printStackTrace();
//                fail(taskContext, "导入过程中出现错误");
                LOGGER.error("导入过程中出现错误:{}", e.getMessage());
            }
        }
        boolean result = true;
        try {
            if (CollectionUtils.isNotEmpty(optionErrorList) ||
                    CollectionUtils.isNotEmpty(rightAnswerErrorList) || CollectionUtils.isNotEmpty(typeErrorList)) {
//                success(taskContext, "导入数据有误,请查看明细", url);
                LOGGER.error("导入数据有误,请查看明细:{}", url);
                return null;
            }
            LOGGER.info("题库导入insertList:", JSONUtil.toJsonStr(insertList));
            if (CollectionUtils.isNotEmpty(insertList)) {
                if (insertList.size() > 100) {
                    int n = insertList.size() / 100;
                    for (int i = 0; i < n; i++) {
                        result = questionLibrarySubjectClient.insertList(insertList.subList(100 * i, 100 * i + 100));
                        if (!result) {
//                            success(taskContext, "数据保存过程中出现错误", url);
                            LOGGER.error("数据保存过程中出现错误:{}", url);
                        }
                    }
                    if (insertList.size() % 100 > 0) {
                        result = questionLibrarySubjectClient.insertList(insertList.subList(100 * n, insertList.size()));
                        if (!result) {
//                            success(taskContext, "数据保存过程中出现错误", url);
                            LOGGER.error("数据保存过程中出现错误:{}", url);
                        }
                    }
                } else {
                    result = questionLibrarySubjectClient.insertList(insertList);
                    if (!result) {
//                        success(taskContext, "数据保存过程中出现错误", url);
                        LOGGER.error("数据保存过程中出现错误:{}", url);
                    }
                }

            } else {
//                success(taskContext, "未检测到数据", "");
                LOGGER.error("未检测到数据:{}", url);

            }

        } catch (Exception e) {
            e.printStackTrace();
//            success(taskContext, "数据保存过程中出现错误", url);
            LOGGER.error("题库导入选项异常:{}", e.getMessage());
        }
        if (result) {
//            success(taskContext, "成功导入" + insertList.size() + "条", url);
            LOGGER.info("成功导入:{}条", insertList.size());

        } else {
//            success(taskContext, "数据保存过程中出现错误", url);
            LOGGER.info("数据保存过程中出现错误:{}", insertList);
        }


        return list;
    }

    public Workbook getFile(String ossUrl) {
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        Workbook book = null;
        URL url;
        try {
            String fileName = ossUrl.substring(ossUrl.lastIndexOf("/") + 1);
            String ossUrlPrefix = ossUrl.substring(0, ossUrl.lastIndexOf("/") + 1);
            ossUrl = ossUrlPrefix + URLEncoder.encode(fileName, "utf-8");
            url = new URL(ossUrl);
            conn = (HttpURLConnection) url.openConnection();
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = conn.getInputStream();
            book = WorkbookFactory.create(inputStream);
        } catch (MalformedURLException e) {
            LOGGER.error("创建ossurl 连接错误", e.getMessage());
        } catch (IOException e) {
            LOGGER.error("创建ossurl 连接错误", e.getMessage());
        } catch (InvalidFormatException e) {
            LOGGER.error("创建Workbook 对象错误", e.getMessage());
        }
        return book;
    }

    public List<ImportExamQuestionSubjectVO> readExcelFile(Workbook book, TaskContext taskContext) {
        List<ImportExamQuestionSubjectVO> list = new ArrayList<ImportExamQuestionSubjectVO>();
        ImportExamQuestionSubjectVO vo = null;

        InputStream in = null;
        try {
            Sheet sheet = book.getSheetAt(0); // 获取Excel的第一个子页
            Row row = null;
            String errorMessage;
            List<String> options;
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                vo = new ImportExamQuestionSubjectVO();
                int index = 0; // 列数
                row = sheet.getRow(i); // 第几个格子
                if (StringUtils.isBlank(row.getCell(0).toString())) {
                    continue;
                }
                int cellNum = row.getLastCellNum();
                //读取所有选项
                options = new ArrayList<String>();
                for (int j = 5; j < cellNum; j++) {
                    try {
                        if (row.getCell(j) != null) {
                            if (CellType.FORMULA.equals(row.getCell(j).getCellTypeEnum())) {
                                continue;
                            }
                            String context = "";
//                            if (row.getCell(j).getCellTypeEnum().equals(CellType.NUMERIC)) {
//                                SimpleDateFormat sdf = null;
//                                if (HSSFDateUtil.isCellDateFormatted(row.getCell(j))) {
//                                    short format = row.getCell(j).getCellStyle().getDataFormat();
//                                    if (format == 20 || format == 32 || format == 183 || (200 <= format && format <= 209)) {
//                                        sdf = new SimpleDateFormat("HH:mm");
//                                    } else if (format == 190 || format == 191) {
//                                        sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
//                                    } else if (format == 14 || format == 31 || format == 57 || format == 58
//                                            || (176 <= format && format <= 178) || (182 <= format && format <= 196)
//                                            || (210 <= format && format <= 213) || (208 == format)) {
//                                        sdf = new SimpleDateFormat("yyyy/MM/dd");
//                                    }
//                                    context = sdf.format(row.getCell(j).getDateCellValue());
//                                }
//                            } else {
//                                context = row.getCell(j).toString();
//                            }
                            row.getCell(j).setCellType(CellType.STRING);
                            context = row.getCell(j).getStringCellValue();
                            context = context.trim();
                            if (StringUtils.isNotBlank(context)) {
                                options.add(context.trim());
                            }

                        }

                    } catch (Exception e) {
                        errorMessage = "第" + (i + 1) + "行" + "第" + (j + 1) + "列解析出错！";
                        e.printStackTrace();
                       // fail(taskContext, errorMessage);
                    }
                }
                try {
                    if (row.getCell(index) != null) {
                        vo.setType(row.getCell(index).toString());
                    }
                    index++;
                } catch (Exception e) {
                    errorMessage = "第" + (i + 2) + "行" + "第" + (index + 1) + "列解析出错！";
                    e.printStackTrace();
                    //fail(taskContext, errorMessage);
                }
                try {
                    if (row.getCell(index) != null) {
                        vo.setStem(row.getCell(index).toString());
                    }
                    index++;
                } catch (Exception e) {
                    errorMessage = "第" + (i + 2) + "行" + "第" + (index + 1) + "列解析出错！";
                    e.printStackTrace();
                    //fail(taskContext, errorMessage);
                }
                try {
                    if (row.getCell(index) != null) {
                        vo.setQuestionLabel(row.getCell(index).toString());
                    }
                    index++;
                } catch (Exception e) {
                    errorMessage = "第" + (i + 2) + "行" + "第" + (index + 1) + "列解析出错！";
                    e.printStackTrace();
                    //fail(taskContext, errorMessage);
                }
                try {
                    if (row.getCell(index) != null) {
                        vo.setAnalysis(row.getCell(index).toString());
                    }
                    index++;
                } catch (Exception e) {
                    errorMessage = "第" + (i + 2) + "行" + "第" + (index + 1) + "列解析出错！";
                    e.printStackTrace();
                    //fail(taskContext, errorMessage);
                }
                try {
                    if (row.getCell(index) != null) {
                        row.getCell(index).setCellType(CellType.STRING);
                        vo.setIsAnswer(row.getCell(index).getStringCellValue());
                    }
                    index++;
                } catch (Exception e) {
//                    errorMessage = "第" + (i + 2) + "行" + "第" + (index + 1) + "列解析出错！";
                    e.printStackTrace();
                    LOGGER.error("第{}行" + "第{}列解析出错！", (i + 2), (index + 1));
//                    fail(taskContext, errorMessage);
                }

                vo.setOption(options);
                list.add(vo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(in);
        }
        return list;
    }

}
