package com.rongwei.trainingcommon.sys.service.impl;

import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.aspose.words.net.System.Data.DataRow;
import com.aspose.words.net.System.Data.DataTable;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.base.exception.CustomException;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.training.domain.DemandSurveyUserAnswerDo;
import com.rongwei.training.domain.TrainingDemandSurveyBackupsDo;
import com.rongwei.training.domain.TrainingDemandSurveyDo;
import com.rongwei.training.vo.DemandUserVo;
import com.rongwei.training.vo.TrainingDemandVo;
import com.rongwei.trainingcommon.sys.dao.DemandSurveyContentDao;
import com.rongwei.trainingcommon.sys.dao.TrainingDemandSurveyBackupsDao;
import com.rongwei.trainingcommon.sys.dao.TrainingDemandSurveyDao;
import com.rongwei.trainingcommon.sys.dao.TraningCommonDao;
import com.rongwei.trainingcommon.sys.service.ExportTrainingDemandService;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * ExportTrainingDemandService class
 *
 * @author XH
 * @date 2023/12/12
 */
@Service
public class ExportTrainingDemandServiceImpl implements ExportTrainingDemandService {
    public static final String DOCX_FILE_PATH = "template/trainingDemand.doc";
    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private TrainingDemandSurveyBackupsDao trainingDemandSurveyBackupsDao;
    @Autowired
    private TrainingDemandSurveyDao trainingDemandSurveyDao;
    @Autowired
    private TrainingDemandServiceImpl trainingDemandService;
    @Autowired
    private DemandSurveyContentDao demandSurveyContentDao;
    @Autowired
    private TraningCommonDao traningCommonDao;
    @Autowired
    private DemandSurveyUserAnswerServiceImpl demandSurveyUserAnswerService;
    // 单选 多选
    public static final String RADIO = "1";
    // 单选 多选
    public static final String CHECK_BOX = "2";
    // 单选 多选
    public static final String INPUT = "3";
    // 题目
    public static final String INPUT_TOPIC = "%s、%s: \n %s";
    // 题目
    public static final String SELECT_TOPIC = "%s、%s: \n%s";

    public static final String CHECK_BOX_ICON = " □  ";

    public static final String RADIO_ICON = " ○  ";
    public static final String CHECKED_ICON = " √ ";

    public static final String OPTIONS = "%s%s";

    public static final String CUSTOM_QUESTION = "customQuestion";

    public static final String[] WORD_KEY = {"name", "year", "companyname", "username", "zw"};

    /**
     * 生成问卷调查word
     *
     * @param surveyId
     */
    @SneakyThrows
    @Override
    public void generatePaper(String surveyId, HttpServletResponse response) {
        log.info("开始生成问卷调查试卷");
        if (StringUtils.isBlank(surveyId)) {
            log.error("参数异常");
            return;
        }
        // 判断问卷调查是否生成
        TrainingDemandSurveyDo trainingDemandSurveyDo = trainingDemandSurveyDao.selectById(surveyId);
        if (trainingDemandSurveyDo == null) {
            log.error("问卷调查已删除");
            return;
        }
        List<TrainingDemandSurveyBackupsDo> trainingDemandSurveyBackupsDos = trainingDemandSurveyBackupsDao.selectList(new LambdaQueryWrapper<TrainingDemandSurveyBackupsDo>()
                .eq(TrainingDemandSurveyBackupsDo::getOldSurveyId, surveyId));
        if (trainingDemandSurveyBackupsDos.isEmpty()) {
            log.error("问卷调查暂未发布");
            return;
        }

        // 获取问卷调查试卷
        List<TrainingDemandVo> surveyContent = demandSurveyContentDao.getSurveyContent(trainingDemandSurveyBackupsDos.get(0).getId(), "");
        DataTable dataTable = createDataTable(surveyContent, false);
        Document document = wordDrawing(WORD_KEY, createWordValue(trainingDemandSurveyDo, null, ""), dataTable, DOCX_FILE_PATH);
        // 文件导出
        exportSingleWord(document, response);
    }

    /**
     * 生成对应用户的问卷调查结果
     * @param surveyId
     * @param userId
     * @param response
     */
    @Override
    public void generateUserPaper(String surveyId, String userId, HttpServletResponse response) {
        if(StringUtils.isBlank(surveyId)||StringUtils.isBlank(userId)){
            throw new RuntimeException("参数异常");
        }
        TrainingDemandSurveyBackupsDo trainingDemandSurveyBackupsDo = trainingDemandSurveyBackupsDao.selectById(surveyId);
        if (trainingDemandSurveyBackupsDo == null) {
            throw new RuntimeException("当前计划已删除");
        }
        TrainingDemandSurveyDo trainingDemandSurveyDo = trainingDemandSurveyDao.selectById(trainingDemandSurveyBackupsDo.getOldSurveyId());
        if (trainingDemandSurveyDo == null) {
            throw new RuntimeException("当前计划已删除");
        }
        List<TrainingDemandVo> surveyContent = demandSurveyContentDao.getSurveyContent(surveyId, userId);
        List<DemandUserVo> demandUserInfo = traningCommonDao.getDemandUserInfo(Arrays.asList(userId));
        DataTable dataTable = createDataTable(surveyContent, true);
        // 绘制word
        Document document = wordDrawing(WORD_KEY, createWordValue(trainingDemandSurveyDo, demandUserInfo, userId), dataTable, DOCX_FILE_PATH);
        // 文件导出
        exportSingleWord(document, response);
    }


    /**
     * 生成所有已填写问卷调查记录的数据
     *
     * @param surveyId
     * @param response
     */
    @Override
    public void generateRecord(String surveyId, HttpServletResponse response) {
        log.info("开始生成问卷调查试卷");
        if (StringUtils.isBlank(surveyId)) {
            log.error("参数异常");
            return;
        }
        // 判断问卷调查是否生成
        TrainingDemandSurveyDo trainingDemandSurveyDo = trainingDemandSurveyDao.selectById(surveyId);
        if (trainingDemandSurveyDo == null) {
            log.error("问卷调查已删除");
            return;
        }
        List<TrainingDemandSurveyBackupsDo> trainingDemandSurveyBackupsDos = trainingDemandSurveyBackupsDao.selectList(new LambdaQueryWrapper<TrainingDemandSurveyBackupsDo>()
                .eq(TrainingDemandSurveyBackupsDo::getOldSurveyId, surveyId));
        if (trainingDemandSurveyBackupsDos.isEmpty()) {
            log.error("问卷调查暂未发布");
            return;
        }
        String backupId = trainingDemandSurveyBackupsDos.get(0).getId();
        // 获取问卷调查题目信息
        List<TrainingDemandVo> surveyContent = demandSurveyContentDao.getSurveyContent(backupId, "");
        // 获取用户填报记录
        List<DemandSurveyUserAnswerDo> userAnswer = demandSurveyUserAnswerService.list(new LambdaQueryWrapper<DemandSurveyUserAnswerDo>().eq(DemandSurveyUserAnswerDo::getSurverid, backupId));
        if (userAnswer.isEmpty()) {
            log.error("参数异常");
            throw new CustomException("当前调查暂无人填写问卷信息");
        }
        // 对问卷答案按照填写人进行分组
        Map<String, List<DemandSurveyUserAnswerDo>> collect = userAnswer.stream().collect(Collectors.groupingBy(BaseDo::getCreateuserid));

        List<String> userIds = userAnswer.stream().map(BaseDo::getCreateuserid).distinct().collect(Collectors.toList());
        List<DemandUserVo> demandUserInfo = traningCommonDao.getDemandUserInfo(userIds);

        Map<String, Document> documentMap = new HashMap<>();
        for (Map.Entry<String, List<DemandSurveyUserAnswerDo>> entry : collect.entrySet()) {
            List<DemandSurveyUserAnswerDo> userAnswerList = entry.getValue();
            surveyContent.forEach(info -> {
                Optional<DemandSurveyUserAnswerDo> first = userAnswerList.stream().filter(answer -> answer.getSurvercontentid().equals(info.getContentid())).findFirst();
                info.setUserAnswer(first.isPresent() ? first.get().getAnswer() : "");
            });
            DataTable dataTable = createDataTable(surveyContent, true);
            // 绘制word
            Document document = wordDrawing(WORD_KEY, createWordValue(trainingDemandSurveyDo, demandUserInfo, entry.getKey()), dataTable, DOCX_FILE_PATH);
            documentMap.put(userAnswerList.get(0).getCreateusername(), document);
        }
        try (ZipOutputStream outputStream = new ZipOutputStream(response.getOutputStream());) {
            for (Map.Entry<String, Document> entry : documentMap.entrySet()) {
                ZipEntry zipEntry = new ZipEntry(entry.getKey() + ".docx");
                outputStream.putNextEntry(zipEntry);
                entry.getValue().save(outputStream, SaveFormat.DOCX);
            }
        } catch (Exception e) {
            log.error("压缩包生成异常");
        }
    }


    /**
     * 创建word模板普通填充内容
     *
     * @param trainingDemandSurveyDo
     * @param sysUserVos
     * @param userId
     * @return
     */
    public String[] createWordValue(TrainingDemandSurveyDo trainingDemandSurveyDo, List<DemandUserVo> sysUserVos, String userId) {
        if (StringUtils.isBlank(userId)) {
           return new String[]{trainingDemandSurveyDo.getName(), trainingDemandSurveyDo.getYear(), "", "", ""};
        }
        DemandUserVo demandUserVo = sysUserVos.stream().filter(info -> info.getId().equals(userId)).findFirst().orElse(null);
        if(demandUserVo==null){
            return new String[]{trainingDemandSurveyDo.getName(), trainingDemandSurveyDo.getYear(), "", "", ""};
        }
        return new String[]{trainingDemandSurveyDo.getName(), trainingDemandSurveyDo.getYear(),
                demandUserVo.getCompanyName(),demandUserVo.getName() , demandUserVo.getRoleName()};
    }

    /**
     * 创建word模板 列表内容
     *
     * @param surveyContent
     * @param showAnswer
     * @return
     */
    public DataTable createDataTable(List<TrainingDemandVo> surveyContent, boolean showAnswer) {
        surveyContent.stream().forEach(info -> {
            if (CUSTOM_QUESTION.equals(info.getModelName())) {
                info.setModelName(info.getQuestionContent());
                info.setQuestionContent("");
            }
        });
        LinkedHashMap<String, List<TrainingDemandVo>> collect = surveyContent.stream()
                .collect(Collectors.groupingBy(TrainingDemandVo::getModelName, LinkedHashMap::new, Collectors.toList()));
        DataTable dataTable = new DataTable("temp");
        dataTable.getColumns().add("num");
        dataTable.getColumns().add("tempName");
        dataTable.getColumns().add("tempContent");
        int i = 1;
        for (Map.Entry<String, List<TrainingDemandVo>> entry : collect.entrySet()) {
            DataRow dataRow = dataTable.newRow();
            dataRow.set("num", i);
            dataRow.set("tempName", entry.getKey());
            int k = 1;
            List<String> content = new ArrayList<>();
            for (TrainingDemandVo trainingDemandVo : entry.getValue()) {
                String questionType = trainingDemandVo.getQuestionType();
                if (INPUT.equals(questionType)) {
                    if (StringUtils.isBlank(trainingDemandVo.getQuestionContent())) {
                        content.add(showAnswer ? trainingDemandVo.getUserAnswer() : "");
                    } else {
                        content.add(String.format(INPUT_TOPIC, k, trainingDemandVo.getQuestionContent(), showAnswer ? trainingDemandVo.getUserAnswer() : ""));
                    }
                } else {
                    content.add(
                            String.format(SELECT_TOPIC, k, trainingDemandVo.getQuestionContent(),
                                    trainingDemandVo.getQuestionOptions().stream().map(info -> {
                                        return String.format(OPTIONS, info, selectShowIcon(showAnswer, questionType, info, trainingDemandVo.getUserAnswer()));
                                    }).collect(Collectors.joining("   ")))
                    );
                }
                k++;
            }
            dataRow.set("tempContent", content.stream().collect(Collectors.joining("\n")));
            dataTable.getRows().add(dataRow);
            i++;
        }
        return dataTable;
    }

    /**
     * 单选和多选所展示的图标
     *
     * @param showAnswer
     * @param questionType
     * @param option
     * @param userAnswer
     * @return
     */
    public String selectShowIcon(boolean showAnswer, String questionType, String option, String userAnswer) {
        if (!showAnswer || StringUtils.isBlank(userAnswer) || StringUtils.isBlank(option)) {
            return CHECK_BOX.equals(questionType) ? CHECK_BOX_ICON : RADIO_ICON;
        }
        return Arrays.asList(userAnswer.split("-;-")).contains(option) ? CHECKED_ICON : CHECK_BOX.equals(questionType) ? CHECK_BOX_ICON : RADIO_ICON;
    }
}
