package com.nokia.tsl_data.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.image.BufferedImage;

import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
import com.nokia.tsl_data.entity.pojo.XSSFWorkbookWrapper;
import com.nokia.tsl_data.util.DateFormatUtil;
import com.nokia.tsl_data.util.TextUtil;
import com.nokia.tsl_data.util.excel.PoiUtil;
import com.nokia.tsl_data.util.excel.entity.CellRect;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ReportServiceV3 {

    @Autowired
    private SysDataDictionaryRepository sysDataDictionaryRepository;
    @Autowired
    private HighQualityCountService highQualityCountService;
    @Autowired
    private ManagementDetailService managementDetailService;
    @Autowired
    private CemMobileExperienceListService cemMobileExperienceListService;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private TslDataService tslDataService;

    private static final DateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");

    /**
     * 每日消息
     */
    public void messageToSend(File file, String day) {
        try (Workbook workbook = WorkbookFactory.create(file)) {
            StringBuffer stringBuffer = new StringBuffer();
            Calendar calendar = DateFormatUtil.toCalendar(day, "yyyyMMdd");
            int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
            stringBuffer.append(calendar.get(Calendar.YEAR))
                    .append("年")
                    .append(calendar.get(Calendar.MONTH) + 1)
                    .append("月截至")
                    .append(dayOfMonth)
                    .append("日移动网投诉情况统计：\n\n");
            // 管理端-移网感知类
            Sheet sheet = workbook.getSheet("管理端-移网感知类");
            Row row;
            if (sheet != null) {
                List<List<Object>> list = new ArrayList<>();
                List<List<Object>> list0 = new ArrayList<>();
                for (int i = 2; i < 14; i++) {
                    row = sheet.getRow(i);
                    double value = row.getCell(dayOfMonth + 6).getNumericCellValue();
                    List<Object> list2 = new ArrayList<>();
                    list2.add(0, value);
                    list2.add(1, row.getCell(dayOfMonth + 7).getStringCellValue());
                    if (value > 0.0) {
                        list.add(list2);
                    }
                    list0.add(list2);
                }
                // 排序
                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
                list0.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
                stringBuffer.append("管理端-移网感知类：");
                if (list.size() == 0) {
                    stringBuffer.append("投诉率：12个地市均已达标，<font color=#FF0000>");
                } else {
                    stringBuffer.append("投诉率：<font color=#FF0000>");
                    for (int i = 0; i < list.size(); i++) {
                        stringBuffer.append(list.get(i).get(1).toString()).append("、");
                    }
                    stringBuffer.deleteCharAt(stringBuffer.length() - 1);
                    stringBuffer.append("</font>未达到目标值，<font color=#FF0000>");
                }
                StringBuffer stringBuffer2 = new StringBuffer();
                for (int i = 0; i < 3; i++) {
                    stringBuffer2.append(list0.get(i).get(1).toString()).append("、");
                }
                stringBuffer2.deleteCharAt(stringBuffer2.length() - 1);
                stringBuffer.append(stringBuffer2.toString()).append("</font>排名靠后。");
            }
            // 管理端-重复投诉率
            sheet = workbook.getSheet("管理端-重复投诉率");
            if (sheet == null || day.endsWith("01")) {
                // 1号忽略重复投诉率
                stringBuffer.append("\n\n");
            } else {
                stringBuffer.append("重复投诉率：<font color=#FF0000>");
                stringBuffer.append(sheet.getRow(3).getCell(0).getStringCellValue()).append("、")
                        .append(sheet.getRow(4).getCell(0).getStringCellValue()).append("、")
                        .append(sheet.getRow(5).getCell(0).getStringCellValue())
                        .append("</font>增长较快。\n\n");
            }
            // 移网综合投诉评价
            sheet = workbook.getSheet("移网综合投诉评价");
            if (sheet != null) {
                stringBuffer.append("移网综合投诉评价：<font color=#FF0000>");
                for (int i = 2; i < 14; i++) {
                    if (sheet.getRow(i).getCell(6).getNumericCellValue() > 0.0d) {
                        stringBuffer.append(sheet.getRow(i).getCell(0).getStringCellValue());
                    } else {
                        break;
                    }
                    stringBuffer.append("、");
                }
                stringBuffer.append("</font>未达到目标值。\n\n");
            }
            // 投诉处理时长、超时工单概况
            sheet = workbook.getSheet("投诉处理时长、超时工单概况");
            if (sheet != null) {
                stringBuffer.append("投诉处理时长、超时工单概况：超时工单：<font color=#FF0000>")
                        .append(sheet.getRow(2).getCell(0).getStringCellValue()).append("、")
                        .append(sheet.getRow(3).getCell(0).getStringCellValue()).append("、")
                        .append(sheet.getRow(4).getCell(0).getStringCellValue())
                        .append("</font>分公司超时工单占比较高，<font color=#FF0000>");
                List<List<Object>> list = new ArrayList<>();
                for (int i = 2; i < 14; i++) {
                    List<Object> list2 = new ArrayList<>();
                    list.add(list2);
                    list2.add(0, sheet.getRow(i).getCell(2).getNumericCellValue());
                    list2.add(1, sheet.getRow(i).getCell(0).getStringCellValue());
                }
                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
                stringBuffer.append(list.get(0).get(1).toString()).append("、")
                        .append(list.get(1).get(1).toString()).append("、")
                        .append(list.get(2).get(1).toString())
                        .append("</font>超时工单数量较多。平均处理时长：本月相对较长的地市为<font color=#FF0000>");

                list = new ArrayList<>();
                for (int i = 2; i < 14; i++) {
                    List<Object> list2 = new ArrayList<>();
                    list.add(list2);
                    list2.add(0, sheet.getRow(i).getCell(8).getNumericCellValue());
                    list2.add(1, sheet.getRow(i).getCell(6).getStringCellValue());
                }
                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
                stringBuffer.append(list.get(0).get(1).toString()).append("、")
                        .append(list.get(1).get(1).toString()).append("、")
                        .append(list.get(2).get(1).toString()).append("</font>。");
            }
            TextUtil.writeToFileWithUTF8(stringBuffer.toString(), Paths.get(file.getParent(), "总结.txt").toString());
        } catch (IOException e) {
            log.error("读取excel文件出错:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 截图
     */
    public void screenShot(File file, String day) {
        if (!file.exists()) {
            throw new RuntimeException(String.format("无法截图，文件%s不存在", file.getAbsolutePath()));
        }
        try (Workbook workbook = WorkbookFactory.create(file)) {
            int dayOfMonth = Integer.parseInt(day.substring(6, 8));
            BufferedImage screenShot;
            Sheet sheet;
            String area;
            // 截图 管理端-移网感知类
            sheet = workbook.getSheet("管理端-移网感知类");
            if (sheet != null) {
                area = "A1:" + CellRect.getColumnName(dayOfMonth + 7) + "15";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "管理端-移网感知类-" + day + ".png").toFile());
            }
            // 截图 服请
            sheet = workbook.getSheet("移网感知服务请求率");
            if (sheet != null) {
                area = "A1:" + CellRect.getColumnName(dayOfMonth + 7) + "15";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "移网感知服务请求率-" + day + ".png").toFile());
            }
            // 截图 重复投诉
            sheet = workbook.getSheet("管理端-重复投诉率");
            if (sheet != null) {
                area = "A1:G16";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "管理端-重复投诉率-" + day + ".png").toFile());
            }
            // 截图 处理时长 超时工单
            sheet = workbook.getSheet("投诉处理时长、超时工单概况");
            if (sheet != null) {
                area = "A1:D15";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "超时工单概况-" + day + ".png").toFile());
                area = "G1:K15";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "投诉处理时长-" + day + ".png").toFile());
            }
            // 截图 移网综合投诉评价
            sheet = workbook.getSheet("移网综合投诉评价");
            if (sheet != null) {
                area = "A1:G15";
                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(file.getParentFile().getAbsolutePath(), "移网综合投诉评价-" + day + ".png").toFile());
            }
        } catch (EncryptedDocumentException | IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 生成报表
     */
    public void generateReport(File file, String day) {
        // 1. 创建workbook并写入各个sheet
        XSSFWorkbookWrapper workbookWrapper = getWorkbook();
        // 1.1 写入sheet 管理端-移网感知类
        managementDetailService.checkStatDayCount(day);
        writeSheet1(workbookWrapper, day);
        log.info("帐期 {} 管理端-移网感知类 sheet写入成功", day);
        // 1.2 写入 服请情况
        cemMobileExperienceListService.checkStatDayCount(day);
        writeSheetServiceRequest(workbookWrapper, day);
        log.info("帐期 {} 服务请求 sheet写入成功", day);
        // 1.3 管理端-重复投诉率
        writeSheetRepeatTs(workbookWrapper, day);
        log.info("帐期 {} 管理端-重复投诉率 sheet写入成功", day);
        // 1.4 写入 投诉处理时长、超时工单概况
        writeSheet3(workbookWrapper, day);
        log.info("帐期 {} 投诉处理时长、超时工单概况 sheet写入成功", day);
        // 1.5 写入三率
        tslDataService.checkStatDayCount(day);
        writeSheet4(workbookWrapper, day);
        log.info("帐期 {} 客户端-三率 sheet写入成功", day);
        // 2. 写入到本地文件
        try (OutputStream outputStream = new FileOutputStream(file)) {
            workbookWrapper.getWorkbook().write(outputStream);
            workbookWrapper.getWorkbook().close();
            // 销毁 workbookWrapper 实例
            workbookWrapper = null;
        } catch (IOException e) {
            log.error("写入失败。。。" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 管理端-重复投诉率
     */
    private void writeSheetRepeatTs(XSSFWorkbookWrapper workbookWrapper, String day) {
        // 计算时间常数
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        try {
            calendar.setTime(DAY_FORMAT.parse(day));
        } catch (ParseException e) {
            log.error("时间字符串解析失败--{}", day);
        }
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int monthOfYear = calendar.get(Calendar.MONTH) + 1;
        // 显示当前和前一天的对比
        int preDayOfMonth = (dayOfMonth > 1) ? dayOfMonth - 1 : dayOfMonth;
        Sheet sheet = workbookWrapper.getWorkbook().createSheet("管理端-重复投诉率");
        Row row;
        Cell cell;
        // 第一行 标题栏
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("重复投诉率（1-%s）", dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 A1 - G1
        PoiUtil.addMergedRegion(sheet, 0, 0, 0, 6);
        // 第二行
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(1);
        cell.setCellValue("工单数");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 B2-C2
        PoiUtil.addMergedRegion(sheet, 1, 1, 1, 2);
        cell = row.createCell(3);
        cell.setCellValue("重复投诉率");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 B2-C2
        PoiUtil.addMergedRegion(sheet, 1, 1, 3, 4);
        cell = row.createCell(5);
        cell.setCellValue("增量");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 F2-G2
        PoiUtil.addMergedRegion(sheet, 1, 1, 5, 6);
        // 第三行
        row = sheet.createRow(2);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(1);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(2);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(3);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(4);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(5);
        cell.setCellValue("工单数");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(6);
        cell.setCellValue("重复投诉率");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 从数据库读取 客户端 重复投诉数据
        List<List<Object>> sheet2Data = managementDetailService.getRepeatTsDataV3(day);
        int rowNum = 3;
        for (List<Object> list : sheet2Data) {
            row = sheet.createRow(rowNum++);
            cell = row.createCell(0);
            // 地市
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 前一天重复工单数
            cell = row.createCell(1);
            cell.setCellValue(((double) list.get(1)));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 当天重复工单数
            cell = row.createCell(2);
            cell.setCellValue(((double) list.get(2)));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 前一天重复投诉率
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 当前重复投诉率
            cell = row.createCell(4);
            cell.setCellValue(((double) list.get(4)));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 重复工单增量
            cell = row.createCell(5);
            cell.setCellValue(((double) list.get(5)));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 重复投诉率增量
            cell = row.createCell(6);
            cell.setCellValue(((double) list.get(6)));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
        }
        // 添加条件格式F4-F15
        PoiUtil.setConditionalFormattingRedToGreen(sheet, 3, 14, 5, 5);
        // 添加条件格式G4-G15
        PoiUtil.setConditionalFormattingRedToGreen(sheet, 3, 14, 6, 6);
        // 设置列宽2048
        for (int i = 0; i <= 6; i++) {
            sheet.setColumnWidth(i, 2848);
        }
        // 设置行高 15.0 ...
        for (int i = 0; i < 16; i++) {
            sheet.getRow(i).setHeightInPoints(15.0F);
        }
    }

    /**
     * 移网综合投诉评价
     */
    private void writeSheet4(XSSFWorkbookWrapper workbookWrapper, String day) {
        List<List<Object>> data = highQualityCountService.getThreeRateOfCityV3(day);
        // 计算时间常数
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        try {
            calendar.setTime(DAY_FORMAT.parse(day));
        } catch (ParseException e) {
            log.error("时间字符串解析失败--{}", day);
        }
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        Sheet sheet4 = workbookWrapper.getWorkbook().createSheet("移网综合投诉评价");
        Row row;
        Cell cell;
        row = sheet4.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("移网综合投诉评价（1-%s）", dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 A1 - D1
        PoiUtil.addMergedRegion(sheet4, 0, 0, 0, 6);
        // 客户端-投诉问题解决满意度 第二行
        row = sheet4.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(1);
        cell.setCellValue("满意率");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(2);
        cell.setCellValue("解决率");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(3);
        cell.setCellValue("响应率");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(4);
        cell.setCellValue("综合评价");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(5);
        cell.setCellValue("达标值");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(6);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 写入各地市数据
        int rowNum = 2;
        for (List<Object> list : data) {
            row = sheet4.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 满意率
            cell = row.createCell(1);
            cell.setCellValue((double) list.get(1));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 解决率
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 相应率
            cell = row.createCell(3);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 综合评价
            cell = row.createCell(4);
            // 移网综合投诉评价“三率”=响应率*0.1+解决率*0.4+满意率*0.5
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 达标值
            cell = row.createCell(5);
            cell.setCellValue((double) list.get(5));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
            // 与达标值差距
            cell = row.createCell(6);
            cell.setCellValue((double) list.get(6));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
        }
        // 设置条件格式D3-D14
        PoiUtil.setConditionalFormattingGreenToRed(sheet4, 2, 13, 6, 6);
        // 设置列宽 2048 1304 2048 2304
        for (int i = 0; i < 7; i++) {
            sheet4.setColumnWidth(i, 2848);
        }
        // 设置行高 15.0 15.0...
        for (int i = 0; i < 15; i++) {
            sheet4.getRow(i).setHeightInPoints(15.0F);
        }
    }

    /**
     * 投诉处理时长、超时工单概况
     */
    private void writeSheet3(XSSFWorkbookWrapper workbookWrapper, String day) {
        // 计算时间常数
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        try {
            calendar.setTime(DAY_FORMAT.parse(day));
        } catch (ParseException e) {
            log.error("时间字符串解析失败--{}", day);
        }
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        // 修正，MONTH是从0开始
        int monthOfYear = calendar.get(Calendar.MONTH) + 1;
        int preMonthOfYear = monthOfYear > 1 ? monthOfYear - 1 : 12;
        Sheet sheet = workbookWrapper.getWorkbook().createSheet("投诉处理时长、超时工单概况");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        // 第一行
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("超时工单情况（1-%s）", dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 A1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
        PoiUtil.addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(6);
        cell.setCellValue(String.format("平均处理时长（1-%s）", dayOfMonth));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 合并单元格 G1 - J1
        rangeAddress = new CellRangeAddress(0, 0, 6, 10);
        PoiUtil.addMergedRegion(sheet, rangeAddress);
        // 第二行
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(1);
        cell.setCellValue("工单数");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(2);
        cell.setCellValue("超时工单数");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(3);
        cell.setCellValue("超时工单占比");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(6);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(7);
        cell.setCellValue(String.format("%s月", preMonthOfYear));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(8);
        cell.setCellValue(String.format("%s月", monthOfYear));
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(9);
        cell.setCellValue("目标值");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        cell = row.createCell(10);
        cell.setCellValue("与目标值差距");
        cell.setCellStyle(workbookWrapper.getCellStyle3());
        // 写入超时工单情况
        List<List<Object>> sheet3Data1 = workFlowService.getTimeoutCountInfo(day);
        int rowNum = 2;
        for (List<Object> list : sheet3Data1) {
            row = sheet.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 工单数
            cell = row.createCell(1);
            cell.setCellValue((long) list.get(1));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 超时工单数
            cell = row.createCell(2);
            cell.setCellValue((long) list.get(2));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 超时工单占比
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(workbookWrapper.getCellStyle2());
        }
        // 设置条件格式D3-D14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, 3, 3);
        // 写入平均处理时长
        List<List<Object>> sheet3Data2 = workFlowService.getCostTimeInfo(day);
        rowNum = 2;
        for (List<Object> list : sheet3Data2) {
            row = sheet.getRow(rowNum++);
            // 地市
            cell = row.createCell(6);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // 上月
            cell = row.createCell(7);
            cell.setCellValue((double) list.get(1));
            cell.setCellStyle(workbookWrapper.getCellStyle5());
            // 当月
            cell = row.createCell(8);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(workbookWrapper.getCellStyle5());
            // 目标值
            cell = row.createCell(9);
            cell.setCellValue((int) list.get(3));
            cell.setCellStyle(workbookWrapper.getCellStyle5());
            // 涨幅
            cell = row.createCell(10);
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(workbookWrapper.getCellStyle5());
        }
        // 设置条件格式K3-K14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, 10, 10);
        // 设置列宽 2048 2276*3 2048*3 2276*2 3612
        for (int i = 0; i < 10; i++) {
            sheet.setColumnWidth(i, 2848);
        }
        // 设置行高 14.25 25.5 14.25...
        for (int i = 0; i < 15; i++) {
            sheet.getRow(i).setHeightInPoints(15.0F);
        }
    }

    /**
     * 管理端-移网感知类 2024年适配需求
     */
    private void writeSheet1(XSSFWorkbookWrapper workbookWrapper, String day) {
        String sheetName = "管理端-移网感知类";
        // 获取数据
        Map<String, List<Object>> seet1Data = managementDetailService.getSheet1DataV3(day);
        // 计算天数
        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
        int dayOfMonth = date.getDayOfMonth();
        int monthOfYear = date.getMonthValue();
        Sheet sheet = workbookWrapper.getWorkbook().createSheet(sheetName);
        Row row;
        Cell cell;
        // 第一行 标题栏
        cell = sheet.createRow(0).createCell(0);
        cell.setCellValue(day.substring(0, 4) + "年" + monthOfYear
                + "客服投诉清单各地市投诉率情况（" + sheetName + "）");
        cell.setCellStyle(workbookWrapper.getCellStyle4());
        PoiUtil.addMergedRegion(sheet, 0, 0, 0, dayOfMonth + 7);
        // 第二行 列名
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        for (int i = 1; i <= dayOfMonth; i++) {
            cell = row.createCell(i);
            cell.setCellValue(i + "日");
            cell.setCellStyle(workbookWrapper.getCellStyle1());
        }
        cell = row.createCell(dayOfMonth + 1);
        cell.setCellValue("投诉总量");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 2);
        cell.setCellValue("用户数");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 3);
        cell.setCellValue("目前万投率");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 4);
        cell.setCellValue("本月预测");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 5);
        cell.setCellValue("目标值");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 6);
        cell.setCellValue("与目标差距");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 7);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        int rowNum = 2;
        int cellNum = 0;
        // 写入各地市数据
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            row = sheet.createRow(rowNum++);
            // 写入A列的地市
            cell = row.createCell(cellNum++);
            cell.setCellValue(area);
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            for (Object obj : seet1Data.get(area)) {
                cell = row.createCell(cellNum++);
                cell.setCellValue(Double.parseDouble(obj.toString()));
                cell.setCellStyle(workbookWrapper.getCellStyle1());
            }
            // 写入最后一列的地市
            cell = row.createCell(cellNum);
            cell.setCellValue(area);
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // cellNum复位
            cellNum = 0;
        }
        // 写入全省数据
        row = sheet.createRow(rowNum);
        // 写入A列的地市
        cell = row.createCell(cellNum++);
        cell.setCellValue("全省");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        for (Object obj : seet1Data.get("全省")) {
            cell = row.createCell(cellNum++);
            cell.setCellValue(Double.parseDouble(obj.toString()));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
        }
        // 写入最后一列的地市
        cell = row.createCell(cellNum);
        cell.setCellValue("全省");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        // 3-15行（2-14）dayOfMonth+2 - dayOfMonth+6是浮点数，设置为显示小数点后2位
        for (int i = 2; i <= 14; i++) {
            row = sheet.getRow(i);
            for (int j = dayOfMonth + 2; j <= dayOfMonth + 6; j++) {
                cell = row.getCell(j);
                cell.setCellStyle(workbookWrapper.getCellStyle5());
            }
        }
        // 添加条件格式B15-V15
        PoiUtil.setConditionalFormattingGreenToRed(sheet, rowNum, rowNum, 1, dayOfMonth);
        // 添加条件格式(dayOfMonth+3)(3-14)
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 3, dayOfMonth + 3);
        // 添加条件格式Z3-Z14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 4, dayOfMonth + 4);
        // 添加条件格式AB3-AB14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 6, dayOfMonth + 6);
        // 设置sheet的列宽
        sheet.setColumnWidth(0, 1600);
        for (int i = 1; i <= dayOfMonth; i++) {
            sheet.setColumnWidth(i, 1100);
        }
        sheet.setColumnWidth(dayOfMonth + 1, 1700);
        sheet.setColumnWidth(dayOfMonth + 2, 2100);
        sheet.setColumnWidth(dayOfMonth + 3, 2100);
        sheet.setColumnWidth(dayOfMonth + 4, 2100);
        sheet.setColumnWidth(dayOfMonth + 5, 1700);
        sheet.setColumnWidth(dayOfMonth + 6, 2100);
        sheet.setColumnWidth(dayOfMonth + 7, 1600);

        // 设置行高 15
        for (int i = 0; i < rowNum; i++) {
            sheet.getRow(i).setHeightInPoints(15F);
        }
    }

    /**
     * 服务请求数据
     */
    private void writeSheetServiceRequest(XSSFWorkbookWrapper workbookWrapper, String day) {
        String sheetName = "移网感知服务请求率";
        // 获取数据
        Map<String, List<Object>> sheetData = cemMobileExperienceListService.getSheetData(day);
        // 计算天数
        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
        int dayOfMonth = date.getDayOfMonth();
        int monthOfYear = date.getMonthValue();
        Sheet sheet = workbookWrapper.getWorkbook().createSheet(sheetName);
        Row row;
        Cell cell;
        // 第一行 标题栏
        cell = sheet.createRow(0).createCell(0);
        cell.setCellValue(day.substring(0, 4) + "年"
                + monthOfYear + "月移网感知（服务请求）");
        cell.setCellStyle(workbookWrapper.getCellStyle4());
        PoiUtil.addMergedRegion(sheet, 0, 0, 0, dayOfMonth + 7);
        // 第二行 列名
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        for (int i = 1; i <= dayOfMonth; i++) {
            cell = row.createCell(i);
            cell.setCellValue(i + "日");
            cell.setCellStyle(workbookWrapper.getCellStyle1());
        }
        cell = row.createCell(dayOfMonth + 1);
        cell.setCellValue("服请总数");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 2);
        cell.setCellValue("用户数");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 3);
        cell.setCellValue("目前万投率");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 4);
        cell.setCellValue("本月预测");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 5);
        cell.setCellValue("目标值");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 6);
        cell.setCellValue("与目标差距");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        cell = row.createCell(dayOfMonth + 7);
        cell.setCellValue("地市");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        int rowNum = 2;
        int cellNum = 0;
        // 写入各地市数据
        for (String area : sysDataDictionaryRepository.findAllCityName()) {
            row = sheet.createRow(rowNum++);
            // 写入A列的地市
            cell = row.createCell(cellNum++);
            cell.setCellValue(area);
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            for (Object obj : sheetData.get(area)) {
                cell = row.createCell(cellNum++);
                cell.setCellValue(Double.parseDouble(obj.toString()));
                cell.setCellStyle(workbookWrapper.getCellStyle1());
            }
            // 写入最后一列的地市
            cell = row.createCell(cellNum);
            cell.setCellValue(area);
            cell.setCellStyle(workbookWrapper.getCellStyle1());
            // cellNum复位
            cellNum = 0;
        }
        // 写入全省数据
        row = sheet.createRow(rowNum);
        // 写入A列的地市
        cell = row.createCell(cellNum++);
        cell.setCellValue("全省");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        for (Object obj : sheetData.get("全省")) {
            cell = row.createCell(cellNum++);
            cell.setCellValue(Double.parseDouble(obj.toString()));
            cell.setCellStyle(workbookWrapper.getCellStyle1());
        }
        // 写入最后一列的地市
        cell = row.createCell(cellNum);
        cell.setCellValue("全省");
        cell.setCellStyle(workbookWrapper.getCellStyle1());
        // 3-15行（2-14）dayOfMonth+2 - dayOfMonth+6是浮点数，设置为显示小数点后2位
        for (int i = 2; i <= 14; i++) {
            row = sheet.getRow(i);
            for (int j = dayOfMonth + 2; j <= dayOfMonth + 6; j++) {
                cell = row.getCell(j);
                cell.setCellStyle(workbookWrapper.getCellStyle5());
            }
        }
        // 添加条件格式B15-V15
        PoiUtil.setConditionalFormattingGreenToRed(sheet, rowNum, rowNum, 1, dayOfMonth);
        // 添加条件格式(dayOfMonth+3)(3-14)
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 3, dayOfMonth + 3);
        // 添加条件格式Z3-Z14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 4, dayOfMonth + 4);
        // 添加条件格式AB3-AB14
        PoiUtil.setConditionalFormattingGreenToRed(sheet, 2, 13, dayOfMonth + 6, dayOfMonth + 6);
        // 设置sheet的列宽
        sheet.setColumnWidth(0, 1600);
        for (int i = 1; i <= dayOfMonth; i++) {
            sheet.setColumnWidth(i, 1300);
        }
        sheet.setColumnWidth(dayOfMonth + 1, 1700);
        sheet.setColumnWidth(dayOfMonth + 2, 2100);
        sheet.setColumnWidth(dayOfMonth + 3, 2100);
        sheet.setColumnWidth(dayOfMonth + 4, 2100);
        sheet.setColumnWidth(dayOfMonth + 5, 1700);
        sheet.setColumnWidth(dayOfMonth + 6, 2100);
        sheet.setColumnWidth(dayOfMonth + 7, 1600);

        // 设置行高 15
        for (int i = 0; i < rowNum; i++) {
            sheet.getRow(i).setHeightInPoints(15F);
        }
    }

    /**
     * 获取一个 XSSFWorkbook 并初始化几个需要的格式
     */
    private XSSFWorkbookWrapper getWorkbook() {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFWorkbookWrapper workbookWrapper = new XSSFWorkbookWrapper();
        XSSFDataFormat dataFormat = workbook.createDataFormat();
        workbookWrapper.setWorkbook(workbook);
        // 基本模式 微软雅黑 10号字 带全边框 水平居中
        XSSFCellStyle baseStyle = workbook.createCellStyle();
        XSSFFont font = workbook.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 10);
        baseStyle.setFont(font);
        baseStyle.setAlignment(HorizontalAlignment.CENTER);
        baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        baseStyle.setBorderBottom(BorderStyle.THIN);
        baseStyle.setBorderTop(BorderStyle.THIN);
        baseStyle.setBorderLeft(BorderStyle.THIN);
        baseStyle.setBorderRight(BorderStyle.THIN);
        // cellStyle1 基本模式 微软雅黑 10号字 带全边框 水平居中
        workbookWrapper.setCellStyle1(baseStyle);
        workbookWrapper.setCellStyle2(baseStyle.copy());
        workbookWrapper.setCellStyle3(baseStyle.copy());
        workbookWrapper.setCellStyle4(baseStyle.copy());
        // 2位小数
        workbookWrapper.setCellStyle5(baseStyle.copy());
        // cellStyle2 百分比 2位小数
        workbookWrapper.getCellStyle2().setDataFormat(dataFormat.getFormat("0.00%"));
        // cellStyle3 背景色 FFAEAAAA
        XSSFColor color = new XSSFColor();
        color.setARGBHex("FFAEAAAA");
        workbookWrapper.getCellStyle3().setFillPattern(FillPatternType.SOLID_FOREGROUND);
        workbookWrapper.getCellStyle3().setFillForegroundColor(color);
        // cellStyle4 背景色 FFAEAAAA 加粗
        XSSFFont font2 = workbook.createFont();
        font2.setFontName("微软雅黑");
        font2.setBold(true);
        font2.setFontHeightInPoints((short) 10);
        workbookWrapper.getCellStyle4().setFont(font2);
        workbookWrapper.getCellStyle4().setFillPattern(FillPatternType.SOLID_FOREGROUND);
        workbookWrapper.getCellStyle4().setFillForegroundColor(color);
        // cellStyle5 2位小数
        workbookWrapper.getCellStyle5().setDataFormat(dataFormat.getFormat("0.00"));
        return workbookWrapper;
    }
}
