package com.fms.system.service.impl;

import com.fms.common.exception.ServiceException;
import com.fms.common.utils.DateUtils;
import com.fms.common.utils.StringUtils;
import com.fms.common.utils.bean.BeanValidators;
import com.fms.system.domain.Failure;
import com.fms.system.mapper.FailureMapper;
import com.fms.system.service.IFailureService;
import com.fms.system.service.ISysConfigService;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.Validator;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

/**
 * 故障记录Service业务层处理
 * 
 * @author Allen
 * @date 2024-05-14
 */
@Service
public class FailureServiceImpl implements IFailureService {
    private static final Logger log = LoggerFactory.getLogger(FailureServiceImpl.class);
    @Autowired
    private FailureMapper failureMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    protected Validator validator;

    /**
     * 查询故障记录
     *
     * @param id 故障记录主键
     * @return 故障记录
     */
    @Override
    public Failure selectFailureById(Long id) {
        return failureMapper.selectFailureById(id);
    }

    /**
     * 查询故障记录列表
     *
     * @param failure 故障记录
     * @return 故障记录
     */
    @Override
    public List<Failure> selectFailureList(Failure failure) {
        return failureMapper.selectFailureList(failure);
    }

    /**
     * 新增故障记录
     *
     * @param failure 故障记录
     * @return 结果
     */
    @Override
    public int insertFailure(Failure failure) {
        failure.setCreateTime(DateUtils.getNowDate());
        return failureMapper.insertFailure(failure);
    }

    /**
     * 修改故障记录
     *
     * @param failure 故障记录
     * @return 结果
     */
    @Override
    public int updateFailure(Failure failure) {
        failure.setUpdateTime(DateUtils.getNowDate());
        return failureMapper.updateFailure(failure);
    }

    /**
     * 批量删除故障记录
     *
     * @param ids 需要删除的故障记录主键
     * @return 结果
     */
    @Override
    public int deleteFailureByIds(Long[] ids) {
        return failureMapper.deleteFailureByIds(ids);
    }

    /**
     * 删除故障记录信息
     *
     * @param id 故障记录主键
     * @return 结果
     */
    @Override
    public int deleteFailureById(Long id) {
        return failureMapper.deleteFailureById(id);
    }

    @Override
    public String importData(List<Failure> failureList, boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(failureList) || failureList.size() == 0) {
            throw new ServiceException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (Failure failure : failureList) {
            try {
                // 验证是否存在这个用户
                Failure f = failureMapper.selectFailureById(failure.getId());
                if (StringUtils.isNull(f)) {
                    BeanValidators.validateWithException(validator, failure);
                    failure.setCreateBy(operName);
                    failureMapper.insertFailure(failure);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、id " + failure.getId() + " 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, failure);
                    failure.setUpdateBy(operName);
                    failureMapper.updateFailure(failure);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、id " + failure.getId() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、id " + failure.getId() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + failure.getId() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public String generateReport(String reportMonth, String major) {
        String docPath = "";

        // 创建一个新的Word文档
        XWPFDocument document = new XWPFDocument();

        // 故障总数根据时间和故障专业获取总数
        // 创建另一个段落
        XWPFRun runParagraph = createPara(document);
        Integer count = failureMapper.getMajorCount(reportMonth, major);
        runParagraph.setText(major + "专业。共统计故障" + count + "起");

        // 获取top5的故障件名称
        List<String> top5UnserviceableCompName = failureMapper.getTop5UnserviceableCompName(reportMonth, major);

        if (!CollectionUtils.isEmpty(top5UnserviceableCompName)) {
            StringJoiner sj = new StringJoiner("、");
            for (String compName : top5UnserviceableCompName) {
                sj.add(compName);
            }
            runParagraph.setText("，故障主要集中在" + sj + "等。");
            // loop top5 的故障信息
            // loop start
            for (String compName : top5UnserviceableCompName) {
                XWPFRun runPara = createPara(document);
                // top n的故障数量
                Integer failureCount = failureMapper.getFailureCount(reportMonth, compName, major);
                runPara.setText(compName + "故障" + failureCount + "起");
                // top n的 top5故障描述
                List<String> top5FailureDescription = failureMapper.getFailureDescription(reportMonth, compName, major);
                if (!CollectionUtils.isEmpty(top5FailureDescription)) {
                    StringJoiner descSj = new StringJoiner("；");
                    for (String desc : top5FailureDescription) {
                        descSj.add(desc);
                    }
                    runPara.setText("，故障模式主要是" + descSj + "等");
                }
                // top n的 top5故障原因
                List<String> top5FailureCause = failureMapper.getFailureCause(reportMonth, compName, major);
                if (!CollectionUtils.isEmpty(top5FailureCause)) {
                    StringJoiner causeSj = new StringJoiner("、");
                    for (String cause : top5FailureCause) {
                        causeSj.add(cause);
                    }
                    runPara.setText("，原因主要是" + causeSj + "等");
                }
                // top n的 top3型别
                List<String> top3CompType = failureMapper.getFailureCompType(reportMonth, compName, major);
                if (!CollectionUtils.isEmpty(top3CompType)) {
                    StringJoiner numSj = new StringJoiner("、");
                    for (String num : top3CompType) {
                        numSj.add(num);
                    }
                    runPara.setText("，主要集中在" + numSj + "等。");
                }
            }
            // loop end
        } else {
            log.warn("获取top5的故障件名称为null");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("HHmmssSSS");

        // 获取当前时间
        Date now = new Date();

        // 格式化当前时间为字符串
        String currentTime = sdf.format(now);
        String directoryPath = "d:/fms/report/";
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        docPath = directoryPath+"故障报告-"+ reportMonth + "-" + major + "-" +currentTime + ".docx";
        // 将文档写入文件
        try (FileOutputStream out = new FileOutputStream(docPath)) {
            document.write(out);
        } catch (IOException e) {
            log.error("文档写入文件异常", e);
        }

        // 关闭文档
        try {
            document.close();
        } catch (IOException e) {
            log.error("关闭文档异常", e);
        }
        return docPath;
    }

    @Override
    public List<Map> getMajorOption() {
        return failureMapper.getMajorOption();
    }

    private XWPFRun createPara(XWPFDocument document){
        // 创建一个段落
        XWPFParagraph paragraph = document.createParagraph();

        // 设置段落缩进：2个字符
        paragraph.setIndentationFirstLine(3 * 240); // 1字符约等于240 twip

        // 设置段前段后间距为0行
        paragraph.setSpacingBefore(0);
        paragraph.setSpacingAfter(0);

        // 设置行距为固定值28.5磅
        CTPPr ppr = paragraph.getCTP().getPPr();
        if (ppr == null) {
            ppr = paragraph.getCTP().addNewPPr();
        }
        CTSpacing spacing = ppr.getSpacing() == null ? ppr.addNewSpacing() : ppr.getSpacing();
        spacing.setLineRule(STLineSpacingRule.EXACT);
        spacing.setLine(new BigInteger(String.valueOf(570))); // 28.5磅，单位是twips 28.5 * 20

        // 创建一个运行来包含文本
        XWPFRun run = paragraph.createRun();

        // 设置字体大小为三号（16磅）
        run.setFontSize(16);

        // 设置字体样式为仿宋GB
        run.setFontFamily("仿宋_GB2312");
        return run;
    }
}
