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

import com.aspose.words.Document;
import com.aspose.words.MailMergeCleanupOptions;
import com.aspose.words.net.System.Data.DataRelation;
import com.aspose.words.net.System.Data.DataRow;
import com.aspose.words.net.System.Data.DataSet;
import com.aspose.words.net.System.Data.DataTable;
import com.rongwei.rwcommon.base.exception.CustomException;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.training.domain.TrainingDemandSurveyBackupsDo;
import com.rongwei.training.vo.QuestionnaireRecordingVo;
import com.rongwei.trainingcommon.sys.dao.TrainingDemandSurveyBackupsDao;
import com.rongwei.trainingcommon.sys.service.ExportQuestionnaireRecordingsService;
import com.rongwei.trainingcommon.sys.service.TrainingDemandSurveyBackupsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ExportQuestionnaireRecordingsServiceImpl class
 *
 * @author XH
 * @date 2024/06/06
 */
@Service
public class ExportQuestionnaireRecordingsServiceImpl implements ExportQuestionnaireRecordingsService {
    /**
     * 模板地址
     */
    public static final String TEMP_PATH = "template/TrainingNeedsSurveyReport.docx";
    public static final SimpleDateFormat YYYY_MM_DD = new SimpleDateFormat("yyyy-MM-dd");
    /**
     * 培训模板总结
     */
    public static final String SUMMARY = "1、培训%s：\n" +
            "培训%s方面员工希望提高自己的%s，根据调查表结果显示，培训内容方面侧重于%s。\n" +
            "\n" +
            "2、培训%s：\n" +
            "培训%s方面以%s、%s、%s等内容为主，结合其他内容进行讲解\n" +
            "\n" +
            "3、%s：\n" +
            "%s方面，重点收集员工能看懂，易看懂的%s，结合%s提高培训的效率。\n" +
            "\n" +
            "4、%s：%s以%s、%s为主，分层级进行讲授。";
    public static final String FIRST_PREFIX = "为了解从业人员安全培训工作重点，本次调查针对培训基本内容和培训具体内容分别展开调查，结果如下：";
    public static final String THIRD_PREFIX = "为进一步提高安全培训质量，本次调查针对培训形式和授课人员分别展开调查，结果如下：";
    public static final String SECOND_SUFFIX = "调查结果显示，在%s培训方面，需求度最高的是%s方面的内容，需求度为 %s％；在%s方面，培训需求最高的是%s（%s％）、%s（%s％）、%s（%s％）等。";
    public static final String FOURTH_SUFFIX = "调查结果显示，在%s方面，员工最喜闻乐见的形式是%s需求度为%s％，在%s方面，员工希望以%s为主要授课人员，需求度为%s％。";
    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private TrainingDemandSurveyBackupsService trainingDemandSurveyBackupsService;
    @Autowired
    private TrainingDemandSurveyBackupsDao trainingDemandSurveyBackupsDao;

    /**
     * 导出word
     *
     * @return
     */
    @Override
    public void exportWord(String id, HttpServletResponse response) {
        log.info("开始通过：{}导出分析报告", id);
        this.getWordLicense();
        // 获取培训需求调查报表
        TrainingDemandSurveyBackupsDo demandSurvey = trainingDemandSurveyBackupsService.getById(id);
        if (demandSurvey == null) {
            log.error("无法根据ID 获取到培训需求调查信息");
            throw new CustomException("无法获取到培训需求调查信息");
        }
        // 培训年份
        String year = demandSurvey.getYear();
        // 发布时间
        Date releasetime = demandSurvey.getReleasetime();
        // 参与培训用户(下发问卷的数量)
        int copiesTotal = demandSurvey.getParticipateuserid().split(",").length;
        // 已参与培训的用户(参与用户的数量)
        int submitTotal = StringUtils.isBlank(demandSurvey.getParticipatinguserid()) ? 0 : demandSurvey.getParticipatinguserid().split(",").length;
        // 计算回收率
        BigDecimal submitRate = calculatePercentage(submitTotal, copiesTotal);
        // 获取用户问卷情况
        List<QuestionnaireRecordingVo> questionnaireInformation = trainingDemandSurveyBackupsDao.getQuestionnaireInformation(id);
        // 对数据按照项目进行分组
        LinkedHashMap<String, List<QuestionnaireRecordingVo>> collect = questionnaireInformation.stream().collect(Collectors.groupingBy(QuestionnaireRecordingVo::getTempId, LinkedHashMap::new, Collectors.toList()));

        try {
            ClassPathResource classPathResource = new ClassPathResource(TEMP_PATH);
            Document doc = new Document(classPathResource.getInputStream());
            assembleExport(year, releasetime, copiesTotal, submitTotal, submitRate, collect, doc);
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=ProblemTrackingAndResolution.docx");
            doc.save(response.getOutputStream(), com.aspose.words.SaveFormat.DOCX);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException("安全培训需求调查分析报告导出异常");
        }
    }

    /**
     * 组装填充模板的数据
     *
     * @param year
     * @param releasetime
     * @param copiesTotal
     * @param submitTotal
     * @param submitRate
     */
    public void assembleExport(String year, Date releasetime, int copiesTotal,
                               int submitTotal, BigDecimal submitRate,
                               LinkedHashMap<String, List<QuestionnaireRecordingVo>> collect,
                               Document doc) throws Exception {

        List<List<QuestionnaireRecordingVo>> values = new ArrayList<>(collect.values());
        // 非列表数据
        Map<String, String> singleDataMap = new HashMap<>();
        singleDataMap.put("year", year);
        singleDataMap.put("releaseDate", YYYY_MM_DD.format(releasetime));
        singleDataMap.put("copiesTotal", String.valueOf(copiesTotal));
        singleDataMap.put("submitTotal", String.valueOf(submitTotal));
        singleDataMap.put("submitRate", submitRate.toString());
        singleDataMap.put("year2", year);
        // 项目模板信息
        DataTable projectTemp = new DataTable("list");
        // 前缀
        projectTemp.getColumns().add("prefix");
        // 序号
        projectTemp.getColumns().add("index");
        // 项目名称
        projectTemp.getColumns().add("name1");
        projectTemp.getColumns().add("name2");
        // 后缀
        projectTemp.getColumns().add("suffix");

        // 项目内容信息
        DataTable questionInfo = new DataTable("project");
        // 问题名称
        questionInfo.getColumns().add("name1");
        // 问题名称
        questionInfo.getColumns().add("content");
        // 迫切需要份数
        questionInfo.getColumns().add("pqxy");
        // 比较需要份数
        questionInfo.getColumns().add("bjxy");
        // 总份数
        questionInfo.getColumns().add("zfs");
        //占比
        questionInfo.getColumns().add("rate");
        int index = 1;
        // 当前的问题信息
        QuestionnaireRecordingVo recordingVo;
        // 当前模板下的所有问题信息
        List<QuestionnaireRecordingVo> listData;
        DataRow projectRow;
        for (Map.Entry<String, List<QuestionnaireRecordingVo>> entry : collect.entrySet()) {
            listData = entry.getValue();
            recordingVo = listData.get(0);
            // 创建新的数据行
            projectRow = projectTemp.newRow();
            if (index == 1) {
                projectRow.set("prefix", FIRST_PREFIX);
            } else if (index == 3) {
                projectRow.set("prefix", THIRD_PREFIX);
            } else {
                projectRow.set("prefix", "");
            }
            projectRow.set("index", index);
            projectRow.set("name1", recordingVo.getTempName());
            projectRow.set("name2", recordingVo.getTempName());

            if (index == 2) {
                projectRow.set("suffix", assembleSecondSuffix(values));
            } else if (index == 4) {
                projectRow.set("suffix", assembleFourthSuffix(values));
            } else {
                projectRow.set("suffix", "");
            }


            /************************创建内容行数据**************************/
            listData.forEach(list -> {
                DataRow questionRow = questionInfo.newRow();
                questionRow.set("name1", list.getTempName());
                questionRow.set("content", list.getQuestionName());
                // 迫切需要份数
                questionRow.set("pqxy", list.getPqxy());
                // 比较需要份数
                questionRow.set("bjxy", list.getBjxy());
                // 总份数
                questionRow.set("zfs", list.getTotalCount());
                //占比
                questionRow.set("rate", calculatePercentage(list.getPqxy() + list.getBjxy(), list.getTotalCount()));
                questionInfo.getRows().add(questionRow);
            });

            projectTemp.getRows().add(projectRow);

            index++;
        }
        if (values.size() >= 4) {
            // 组装培训总结
            singleDataMap.put("summary", assembleSummary(values));
        }
        doc.getMailMerge().setCleanupOptions(MailMergeCleanupOptions.REMOVE_UNUSED_FIELDS);
        // 普通数据合并
        doc.getMailMerge().execute(singleDataMap.keySet().toArray(new String[0]), singleDataMap.values().toArray(new String[0]));
        // 项目数据合并
        DataSet whySet = new DataSet();
        whySet.getTables().add(projectTemp);
        whySet.getTables().add(questionInfo);
        String[] contCols = {"name1"};
        String[] lstCols = {"name1"};
        whySet.getRelations().add(new DataRelation("UserInfo", projectTemp, questionInfo, contCols, lstCols));
        doc.getMailMerge().executeWithRegions(whySet);
        doc.getMailMerge().setCleanupOptions(MailMergeCleanupOptions.REMOVE_EMPTY_TABLE_ROWS);
        doc.getMailMerge().deleteFields();
    }

    /**
     * 组装第二个后缀信息
     * 调查结果显示，在{表1的项目名称}培训方面，需求度最高的是{表1中百分比最高的基本内容名称}方面的内容，需求度为 {该基本内容的百分比}％；
     * 在{表2的项目名称}方面，培训需求最高的是{表2中百分比第一的具体内容名称}（{该具体内容的百分比}％）
     * 、{表2中百分比第二的具体内容名称}（{该具体内容的百分比}％）、{表2中百分比第三的具体内容名称}（{该具体内容的百分比}％）等。
     *
     * @return
     */
    public String assembleSecondSuffix(List<List<QuestionnaireRecordingVo>> values) {
        List<QuestionnaireRecordingVo> firstList = values.get(0);
        List<QuestionnaireRecordingVo> secondList = values.get(1);
        // 对数据排序
        firstList = firstList.stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());
        secondList = secondList.stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());


        return String.format(SECOND_SUFFIX, firstList.get(0).getTempName(), firstList.get(0).getQuestionName(),
                calculatePercentage(firstList.get(0).getPqxy() + firstList.get(0).getBjxy(), firstList.get(0).getTotalCount()),

                secondList.get(0).getTempName(), secondList.get(0).getQuestionName(),
                calculatePercentage(secondList.get(0).getPqxy() + secondList.get(0).getBjxy(), secondList.get(0).getTotalCount()),

                secondList.get(1).getQuestionName(),
                calculatePercentage(secondList.get(1).getPqxy() + secondList.get(1).getBjxy(), secondList.get(1).getTotalCount()),

                secondList.get(2).getQuestionName(),
                calculatePercentage(secondList.get(2).getPqxy() + secondList.get(2).getBjxy(), secondList.get(2).getTotalCount())
        );
    }

    /**
     * 组装第四个后缀信息
     * 调查结果显示，在{表3的项目名称}方面，员工最喜闻乐见的形式是{表3中百分比最高的期望培训形式名称}需求度为{该期望形式百分比}％，
     * 在{表4的项目名称}方面，员工希望以{表4中百分比最高的期望授课人名称}为主要授课人员，需求度为{该期望授课人的百分比}％。
     *
     * @return
     */
    public String assembleFourthSuffix(List<List<QuestionnaireRecordingVo>> values) {

        List<QuestionnaireRecordingVo> firstList = values.get(2);
        List<QuestionnaireRecordingVo> secondList = values.get(3);
        // 对数据排序
        firstList = firstList.stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());
        secondList = secondList.stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());
        return String.format(FOURTH_SUFFIX, firstList.get(0).getTempName(), firstList.get(0).getQuestionName(),
                calculatePercentage(firstList.get(0).getPqxy() + firstList.get(0).getBjxy(), firstList.get(0).getTotalCount()),
                secondList.get(0).getTempName(), secondList.get(0).getQuestionName(),
                calculatePercentage(secondList.get(0).getPqxy() + secondList.get(0).getBjxy(), secondList.get(0).getTotalCount())
        );
    }

    /**
     * 组装项目总结
     * 1、培训{表1的项目名称}：
     * 培训{表1的项目名称}方面员工希望提高自己的{表1中百分比最高的基本内容名称}，根据调查表结果显示，培训内容方面侧重于{表2中百分比第一的具体内容名称}。
     * <p>
     * 2、培训{表2的项目名称}：
     * 培训{表2的项目名称}方面以{表2中百分比第一的具体内容名称}、{表2中百分比第二的具体内容名称}、{表2中百分比第三的具体内容名称}等内容为主，结合其他内容进行讲解
     * <p>
     * 3、{表3的项目名称}：
     * {表3的项目名称}方面，重点收集员工能看懂，易看懂的{表3中百分比最高的期望培训形式名称}，结合{表3中百分比最高的期望培训形式名称}提高培训的效率。
     * <p>
     * <p>
     * 4、{表4的项目名称}：{表4的项目名称}以{表4中百分比第一的期望授课人名称}、{表4中百分比第二的期望授课人名称}为主，分层级进行讲授。
     *
     * @param values
     * @return
     */
    public String assembleSummary(List<List<QuestionnaireRecordingVo>> values) {
        QuestionnaireRecordingVo first = values.get(0).stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList()).get(0);
        List<QuestionnaireRecordingVo> second = values.get(1).stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());
        QuestionnaireRecordingVo third = values.get(2).stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList()).get(0);
        List<QuestionnaireRecordingVo> fourth = values.get(3).stream()
                .sorted(Comparator.comparingInt((QuestionnaireRecordingVo info) -> info.getPqxy() + info.getBjxy()).reversed())
                .collect(Collectors.toList());
        return String.format(String.format(SUMMARY,
                first.getTempName(), first.getTempName(), first.getQuestionName(), second.get(0).getQuestionName(),
                second.get(0).getTempName(),second.get(0).getTempName(), second.get(0).getQuestionName(), second.get(1).getQuestionName(), second.get(2).getQuestionName(),
                third.getTempName(), third.getTempName(), third.getQuestionName(), third.getQuestionName(),
                fourth.get(0).getTempName(),fourth.get(0).getTempName(), fourth.get(0).getQuestionName(), fourth.get(1).getQuestionName()));
    }


    /**
     * 计算百分比
     *
     * @param divisor  除数
     * @param dividend 被除数
     * @return
     */
    public BigDecimal calculatePercentage(int divisor, int dividend) {
        if (divisor == 0 || dividend == 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(divisor)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(dividend), 2, BigDecimal.ROUND_HALF_UP);
    }

    public void getWordLicense() {
        try {
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("license.xml");
            com.aspose.words.License aposeLic = new com.aspose.words.License();
            aposeLic.setLicense(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
