package com.nokia.tsl_data.service;

import com.nokia.tsl_data.dao.HighQualityCountMapper;
import com.nokia.tsl_data.dao.MobileComplaintMapper;
import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
import com.nokia.tsl_data.properties.TslDataProperties;
import com.nokia.tsl_data.util.excel.PoiUtil;
import com.nokia.tsl_data.util.excel.entity.CellRect;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
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.*;

/**
 * 投诉报表数据生成
 */
@Slf4j
@Service
public class ReportServiceV1 {

    @Autowired
    private TslDataService tslDataService;
    @Autowired
    private TslDataProperties tslDataProperties;
    @Autowired
    private HighQualityCountMapper highQualityCountMapper;
    @Autowired
    private HighQualityCountService highQualityCountService;
    @Autowired
    private HighQualityDataService highQualityDataService;
    @Autowired
    private MobileComplaintMapper mobileComplaintMapper;
    @Autowired
    private SysDataDictionaryRepository sysDataDictionaryRepository;

    private XSSFWorkbook workbook = null;
    private XSSFCellStyle cellStyle1 = null;
    private XSSFCellStyle cellStyle2 = null;
    private XSSFCellStyle cellStyle3 = null;

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

    /**
     * 截图任务
     */
    public void screenShotV2(String day) {
        String fileName = tslDataProperties.getOutputFileNamePrefix() + day + ".xlsx";
        // 输出文件路径 增加V2
        File file = Paths.get(tslDataProperties.getOutputPath(), "V2", day, fileName).toFile();
        if (!file.exists()) {
            throw new RuntimeException(String.format("无法截图，文件%s不存在", file.getAbsolutePath()));
        }
        try (Workbook workbook = WorkbookFactory.create(file)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new SimpleDateFormat("yyyyMMdd").parse(day));
            int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
            BufferedImage screenShot;
            // 截图1
            String area = "A1:" + CellRect.getColumnName(dayOfMonth + 7) + "15";
            screenShot = PoiUtil.screenShot(workbook.getSheet("管理端-移网质量类"), area, "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-1-投诉率.png").toFile());
            // 截图2
            String area2 = "A1:" + CellRect.getColumnName(dayOfMonth + 7) + "15";
            screenShot = PoiUtil.screenShot(workbook.getSheet("客户端-战略考核"), area2, "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-2-客户端-战略考核.png").toFile());
            // 截图3 每月1号不发送重复投诉率
            if (!day.endsWith("01")) {
                screenShot = PoiUtil.screenShot(workbook.getSheet("管理端-重复投诉率"), "A1:G16", "微软雅黑");
                ImageIO.write(screenShot, "png",
                        Paths.get(tslDataProperties.getOutputPath(), day, day + "-3-重复投诉率.png").toFile());
            }
            // 截图4 5
            Sheet sheet = workbook.getSheet("投诉处理时长、超时工单概况");
            screenShot = PoiUtil.screenShot(sheet, "A1:D15", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-4-超时工单.png").toFile());
            screenShot = PoiUtil.screenShot(sheet, "G1:J14", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-5-处理时长.png").toFile());
            // 截图6
            sheet = workbook.getSheet("客户端地市三率");
            screenShot = PoiUtil.screenShot(sheet, "A1:J15", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-6-地市三率.png").toFile());
            // 截图7 8 9 区县三率
            sheet = workbook.getSheet("客户端区县三率");
            screenShot = PoiUtil.screenShot(sheet, "A1:F32", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-7-区县响应率.png").toFile());
            screenShot = PoiUtil.screenShot(sheet, "A1:F32", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-8-区县满意度.png").toFile());
            screenShot = PoiUtil.screenShot(sheet, "A1:F32", "微软雅黑");
            ImageIO.write(screenShot, "png",
                    Paths.get(tslDataProperties.getOutputPath(), day, day + "-9-区县解决率.png").toFile());
        } catch (EncryptedDocumentException | IOException | ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 生成报表，版本2，包含区县三率
     */
    public void generateReportV2(String day) {
        String fileName = tslDataProperties.getOutputFileNamePrefix() + day + ".xlsx";
        // 输出路径 增加 V2
        File file = Paths.get(tslDataProperties.getOutputPath(), "V2", day).toFile();
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            System.out.println(mkdirs);
        }
        String dayId = day.substring(0, 4) + "-" + day.substring(4, 6) + "-" + day.substring(6);
        int qualityCountForDay = highQualityCountMapper.selectQualityCountForDay(dayId);
        if (qualityCountForDay == 0) {
            throw new RuntimeException("he_d_high_quality表缺少数据");
        }
        int compCountForDay = mobileComplaintMapper.selectCompCountForDay(day);
        if (compCountForDay == 0) {
            throw new RuntimeException("he_d_mobile_comp表缺少数据");
        }
        // 每次需要重置workbook
        workbook = getWorkbook();
        // 按照顺序写入各个sheet
        // 管理端-移网质量类
        getSheet1V1(day);
        // 客户端-战略考核
        getSheet1_1(day);
        // 管理端-重复投诉率
        getSheet2(day);
        // 投诉处理时长、超时工单概况
        getSheet3(day);
        // 客户端-投诉问题解决满意度 客户端-投诉问题解决率 客户端-投诉问题响应率
        getCityThreeRateSheet(day);
        // 区县三率
        getSheet7(day);
        try (OutputStream outputStream = new FileOutputStream(Paths.get(file.getAbsolutePath(), fileName).toFile())) {
            workbook.write(outputStream);
            workbook.close();
            workbook = null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("写入失败。。。" + e.getMessage());
        }
    }

    public void generateReportV1(String day) {
        String fileName = tslDataProperties.getOutputFileNamePrefix() + day + ".xlsx";
        File file = Paths.get(tslDataProperties.getOutputPath(), "V1", day).toFile();
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            System.out.println(mkdirs);
        }
        String dayId = day.substring(0, 4) + "-" + day.substring(4, 6) + "-" + day.substring(6);
        int qualityCountForDay = highQualityCountMapper.selectQualityCountForDay(dayId);
        if (qualityCountForDay == 0) {
            throw new RuntimeException("he_d_high_quality表缺少数据");
        }
        int compCountForDay = mobileComplaintMapper.selectCompCountForDay(day);
        if (compCountForDay == 0) {
            throw new RuntimeException("he_d_mobile_comp表缺少数据");
        }
        workbook = getWorkbook();
        // 管理端-移网质量类
        getSheet1V1(day);
        // 客户端-战略考核
        getSheet1_1(day);
        // 管理端-重复投诉率
        getSheet2(day);
        // 投诉处理时长、超时工单概况
        getSheet3(day);
        // 客户端-投诉问题解决满意度 客户端-投诉问题解决率 客户端-投诉问题响应率
        getSheet4_6(day);
        try (OutputStream outputStream = new FileOutputStream(Paths.get(file.getAbsolutePath(), fileName).toFile())) {
            workbook.write(outputStream);
            workbook.close();
            workbook = null;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("写入失败。。。" + e.getMessage());
        }
    }

    /**
     * 客户端-投诉问题解决满意度
     * 客户端-投诉问题解决率
     * 客户端-投诉问题响应率
     */
    private void getSheet4_6(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);
        Sheet sheet4 = getWorkbook().createSheet("客户端-投诉问题解决满意度");
        Sheet sheet5 = getWorkbook().createSheet("客户端-投诉问题解决率");
        Sheet sheet6 = getWorkbook().createSheet("客户端-投诉问题响应率");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
        XSSFFont font = getWorkbook().createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 10);
        // 基本模式 微软雅黑 10号字 带全边框 水平居中
        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
        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);
        // 样式1 与base相同
        XSSFCellStyle cellStyle1 = baseStyle.copy();
        // 样式2 百分比 2位小数
        XSSFCellStyle cellStyle2 = baseStyle.copy();
        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
        // 样式3 自动换行 背景色FFE7E6E6 FFAEAAAA
        XSSFCellStyle cellStyle3 = baseStyle.copy();
        // cellStyle3.setWrapText(true);
        XSSFColor color = new XSSFColor();
        color.setARGBHex("FFAEAAAA");
        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle3.setFillForegroundColor(color);

        List<List<List<Object>>> sheet4_6Data = tslDataService.getSheet4_6Data(day);

        // 客户端-投诉问题解决满意度 第一行
        row = sheet4.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("投诉问题解决满意率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
        addMergedRegion(sheet4, rangeAddress);
        // 客户端-投诉问题解决满意度 第二行
        row = sheet4.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("满意率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        int rowNum = 2;
        for (List<Object> list : sheet4_6Data.get(0)) {
            row = sheet4.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 投诉问题解决满意率
            cell = row.createCell(1);
            cell.setCellValue(((double) list.get(1)));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(cellStyle2);
        }
        // 设置条件格式D3-D14
        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
        setConditionalFormatting2(sheet4, rangeAddress);

        // 设置列宽 2048 1304 2048 2304
        for (int i = 0; i < 4; i++) {
            sheet4.setColumnWidth(i, 2848);
        }

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

        // 客户端-投诉问题解决率
        row = sheet5.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("投诉问题解决率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
        addMergedRegion(sheet5, rangeAddress);
        // 客户端-投诉问题解决率 第二行
        row = sheet5.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("解决率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        rowNum = 2;
        for (List<Object> list : sheet4_6Data.get(1)) {
            row = sheet5.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 投诉问题解决率
            cell = row.createCell(1);
            cell.setCellValue(((double) list.get(1)));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(cellStyle2);
        }
        // 设置条件格式D3-D14
        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
        setConditionalFormatting2(sheet5, rangeAddress);

        // 设置列宽 2048 1304 2048 2304
        for (int i = 0; i < 4; i++) {
            sheet5.setColumnWidth(i, 2848);
        }

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

        // 客户端-投诉问题响应率
        row = sheet6.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("投诉问题响应率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
        addMergedRegion(sheet6, rangeAddress);
        // 客户端-投诉问题响应率 第二行
        row = sheet6.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("响应率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        rowNum = 2;
        for (List<Object> list : sheet4_6Data.get(2)) {
            row = sheet6.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 投诉问题解决率
            cell = row.createCell(1);
            cell.setCellValue(((double) list.get(1)));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(cellStyle2);
        }
        // 设置条件格式D3-D14
        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
        setConditionalFormatting2(sheet6, rangeAddress);

        // 设置列宽 2048 1304 2048 2304
        for (int i = 0; i < 4; i++) {
            sheet6.setColumnWidth(i, 2848);
        }

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

    /**
     * 客户端区县三率
     */
    private void getSheet7(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);
        Sheet sheet7 = getWorkbook().createSheet("客户端区县三率");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;

        // 获取响应率数据
        List<List<Object>> timelyContactRateData = highQualityDataService.generateCpTimelyContactOfRegion(day);
        // 第一行 区县投诉问题响应率（1-11）
        row = sheet7.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("区县投诉问题响应率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1-F1
        rangeAddress = new CellRangeAddress(0, 0, 0, 5);
        addMergedRegion(sheet7, rangeAddress);
        // 第二行
        row = sheet7.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("区县");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("响应率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(4);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(5);
        cell.setCellValue("累计未响应");
        cell.setCellStyle(cellStyle3);
        // 写入数据
        int rowNum = 2;
        for (List<Object> list : timelyContactRateData) {
            row = sheet7.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 区县
            cell = row.createCell(1);
            cell.setCellValue(list.get(1).toString());
            cell.setCellStyle(cellStyle1);
            // 响应率
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(3);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(4);
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(cellStyle2);
            // 本月累计未响应工单数
            cell = row.createCell(5);
            cell.setCellValue((int) list.get(5));
            cell.setCellStyle(cellStyle1);
        }
        // 与达标值差距设置条件格式
        rangeAddress = new CellRangeAddress(2, --rowNum, 4, 4);
        setConditionalFormatting2(sheet7, rangeAddress);
        // 设置列宽
        sheet7.setColumnWidth(0, 2848);
        sheet7.setColumnWidth(1, 2848);
        sheet7.setColumnWidth(2, 2848);
        sheet7.setColumnWidth(3, 2848);
        sheet7.setColumnWidth(4, 2848);
        sheet7.setColumnWidth(5, 2848);

        // 获取和写入满意度数据
        List<List<Object>> satisfactionData = highQualityDataService.generateCpSatisfactionOfRegion(day);
        // 第一行 区县投诉问题满意度（1-11）
        row = sheet7.getRow(0);
        cell = row.createCell(7);
        cell.setCellValue(String.format("区县投诉问题满意度（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 H1-M1
        rangeAddress = new CellRangeAddress(0, 0, 7, 12);
        addMergedRegion(sheet7, rangeAddress);
        // 第二行
        row = sheet7.getRow(1);
        cell = row.createCell(7);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(8);
        cell.setCellValue("区县");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(9);
        cell.setCellValue("满意度");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(10);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(11);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(12);
        cell.setCellValue("累计不满意");
        cell.setCellStyle(cellStyle3);
        // 写入数据
        rowNum = 2;
        for (List<Object> list : satisfactionData) {
            row = sheet7.getRow(rowNum++);
            // 地市
            cell = row.createCell(7);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 区县
            cell = row.createCell(8);
            cell.setCellValue(list.get(1).toString());
            cell.setCellStyle(cellStyle1);
            // 响应率
            cell = row.createCell(9);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(10);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(11);
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(cellStyle2);
            // 本月累计未响应工单数
            cell = row.createCell(12);
            cell.setCellValue((int) list.get(5));
            cell.setCellStyle(cellStyle1);
        }
        // 与达标值差距设置条件格式
        rangeAddress = new CellRangeAddress(2, --rowNum, 11, 11);
        setConditionalFormatting2(sheet7, rangeAddress);
        // 设置列宽
        sheet7.setColumnWidth(7, 2848);
        sheet7.setColumnWidth(8, 2848);
        sheet7.setColumnWidth(9, 2848);
        sheet7.setColumnWidth(10, 2848);
        sheet7.setColumnWidth(11, 2848);
        sheet7.setColumnWidth(12, 2848);

        // 获取和写入解决率数据 14到19列 O-T
        List<List<Object>> cpIsOkData = highQualityDataService.generateCpIsOkOfRegion(day);
        // 第一行 区县投诉问题解决率（1-11）
        row = sheet7.getRow(0);
        cell = row.createCell(14);
        cell.setCellValue(String.format("区县投诉问题解决率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 O1-T1
        rangeAddress = new CellRangeAddress(0, 0, 14, 19);
        addMergedRegion(sheet7, rangeAddress);
        // 第二行
        row = sheet7.getRow(1);
        cell = row.createCell(14);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(15);
        cell.setCellValue("区县");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(16);
        cell.setCellValue("解决率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(17);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(18);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(19);
        cell.setCellValue("累计未解决");
        cell.setCellStyle(cellStyle3);
        // 写入数据
        rowNum = 2;
        for (List<Object> list : cpIsOkData) {
            row = sheet7.getRow(rowNum++);
            // 地市
            cell = row.createCell(14);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 区县
            cell = row.createCell(15);
            cell.setCellValue(list.get(1).toString());
            cell.setCellStyle(cellStyle1);
            // 响应率
            cell = row.createCell(16);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            // 达标值
            cell = row.createCell(17);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(cellStyle2);
            // 与达标值差距
            cell = row.createCell(18);
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(cellStyle2);
            // 本月累计未响应工单数
            cell = row.createCell(19);
            cell.setCellValue((int) list.get(5));
            cell.setCellStyle(cellStyle1);
        }
        // 与达标值差距设置条件格式
        rangeAddress = new CellRangeAddress(2, --rowNum, 18, 18);
        setConditionalFormatting2(sheet7, rangeAddress);
        // 设置列宽
        sheet7.setColumnWidth(14, 2848);
        sheet7.setColumnWidth(15, 2848);
        sheet7.setColumnWidth(16, 2848);
        sheet7.setColumnWidth(17, 2848);
        sheet7.setColumnWidth(18, 2848);
        sheet7.setColumnWidth(19, 2848);

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

    private void getCityThreeRateSheet(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);
        Sheet sheet = getWorkbook().createSheet("客户端地市三率");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        // 获取区县三率数据
        Map<String, List<Object>> dataMap = highQualityCountService.generateThreeRateOfCity(day);
        // 第一行
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue("");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue(String.format("投诉问题解决满意率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 B1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 1, 3);
        addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(4);
        cell.setCellValue(String.format("投诉问题解决率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 E1 - G1
        rangeAddress = new CellRangeAddress(0, 0, 4, 6);
        addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(7);
        cell.setCellValue(String.format("投诉问题响应率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 H1 - J1
        rangeAddress = new CellRangeAddress(0, 0, 7, 9);
        addMergedRegion(sheet, rangeAddress);
        // 第二行
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("满意度");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(4);
        cell.setCellValue("解决率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(5);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(6);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(7);
        cell.setCellValue("响应率");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(8);
        cell.setCellValue("达标值");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(9);
        cell.setCellValue("与达标值差距");
        cell.setCellStyle(cellStyle3);
        // 数据行
        int rowNum = 2;
        for (String city : sysDataDictionaryRepository.findAllCityName()) {
            List<Object> list = dataMap.get(city);
            row = sheet.createRow(rowNum++);
            // 地市
            cell = row.createCell(0);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 满意度
            cell = row.createCell(1);
            cell.setCellValue((double) list.get(1));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(2);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(3);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(cellStyle2);
            // 解决率
            cell = row.createCell(4);
            cell.setCellValue((double) list.get(4));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(5);
            cell.setCellValue((double) list.get(5));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(6);
            cell.setCellValue((double) list.get(6));
            cell.setCellStyle(cellStyle2);
            // 响应率
            cell = row.createCell(7);
            cell.setCellValue((double) list.get(7));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(8);
            cell.setCellValue((double) list.get(8));
            cell.setCellStyle(cellStyle2);
            cell = row.createCell(9);
            cell.setCellValue((double) list.get(9));
            cell.setCellStyle(cellStyle2);
        }
        // 设置条件格式
        // 设置条件格式D3-D14
        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
        setConditionalFormatting2(sheet, rangeAddress);
        // 设置条件格式G3-G14
        rangeAddress = new CellRangeAddress(2, 13, 6, 6);
        setConditionalFormatting2(sheet, rangeAddress);
        // 设置条件格式J3-J14
        rangeAddress = new CellRangeAddress(2, 13, 9, 9);
        setConditionalFormatting2(sheet, rangeAddress);
        // 写入全省数据
        List<Object> list = dataMap.get("全省");
        row = sheet.createRow(rowNum);
        // 地市
        cell = row.createCell(0);
        cell.setCellValue(list.get(0).toString());
        cell.setCellStyle(cellStyle1);
        // 满意度
        cell = row.createCell(1);
        cell.setCellValue((double) list.get(1));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(2);
        cell.setCellValue((double) list.get(2));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(3);
        cell.setCellValue((double) list.get(3));
        cell.setCellStyle(cellStyle2);
        // 解决率
        cell = row.createCell(4);
        cell.setCellValue((double) list.get(4));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(5);
        cell.setCellValue((double) list.get(5));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(6);
        cell.setCellValue((double) list.get(6));
        cell.setCellStyle(cellStyle2);
        // 响应率
        cell = row.createCell(7);
        cell.setCellValue((double) list.get(7));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(8);
        cell.setCellValue((double) list.get(8));
        cell.setCellStyle(cellStyle2);
        cell = row.createCell(9);
        cell.setCellValue((double) list.get(9));
        cell.setCellStyle(cellStyle2);

        // 设置列宽
        for (int i = 0; i < 9; i++) {
            sheet.setColumnWidth(i, 2848);
        }

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

    /**
     * 投诉处理时长、超时工单概况
     */
    private void getSheet3(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 = getWorkbook().createSheet("投诉处理时长、超时工单概况");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
        XSSFFont font = getWorkbook().createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 10);
        // 基本模式 微软雅黑 10号字 带全边框 水平居中
        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
        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);
        // 样式1 与base相同
        XSSFCellStyle cellStyle1 = baseStyle.copy();
        // 样式2 百分比 2位小数
        XSSFCellStyle cellStyle2 = baseStyle.copy();
        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
        // 样式3 自动换行 背景色FFE7E6E6 FFAEAAAA
        XSSFCellStyle cellStyle3 = baseStyle.copy();
        // cellStyle3.setWrapText(true);
        XSSFColor color = new XSSFColor();
        color.setARGBHex("FFAEAAAA");
        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle3.setFillForegroundColor(color);
        // 样式4 小数 保留2位
        XSSFCellStyle cellStyle4 = baseStyle.copy();
        cellStyle4.setDataFormat(dataFormat.getFormat("0.00"));

        // 第一行
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("超时工单情况（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1 - D1
        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
        addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(6);
        cell.setCellValue(String.format("平均处理时长（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 G1 - J1
        rangeAddress = new CellRangeAddress(0, 0, 6, 9);
        addMergedRegion(sheet, rangeAddress);

        // 第二行
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("工单数");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue("超时工单数");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue("超时工单占比");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(6);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(7);
        cell.setCellValue(String.format("%s月", preMonthOfYear));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(8);
        cell.setCellValue(String.format("%s月", monthOfYear));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(9);
        cell.setCellValue("涨幅");
        cell.setCellStyle(cellStyle3);

        // 写入超时工单情况
        List<List<Object>> sheet3Data1 = tslDataService.getSheet3Data1(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(cellStyle1);
            // 工单数
            cell = row.createCell(1);
            cell.setCellValue((long) list.get(1));
            cell.setCellStyle(cellStyle1);
            // 超时工单数
            cell = row.createCell(2);
            cell.setCellValue((long) list.get(2));
            cell.setCellStyle(cellStyle1);
            // 超时工单占比
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(cellStyle2);
        }
        // 设置条件格式D3-D14
        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
        setConditionalFormatting(sheet, rangeAddress);

        // 写入平均处理时长
        List<List<Object>> sheet3Data2 = tslDataService.getSheet3Data2(day);
        rowNum = 2;
        for (List<Object> list : sheet3Data2) {
            row = sheet.getRow(rowNum++);
            // 地市
            cell = row.createCell(6);
            cell.setCellValue(list.get(0).toString());
            cell.setCellStyle(cellStyle1);
            // 上月
            cell = row.createCell(7);
            cell.setCellValue((double) list.get(1));
            cell.setCellStyle(cellStyle4);
            // 当月
            cell = row.createCell(8);
            cell.setCellValue((double) list.get(2));
            cell.setCellStyle(cellStyle4);
            // 涨幅
            cell = row.createCell(9);
            cell.setCellValue((double) list.get(3));
            cell.setCellStyle(cellStyle4);
        }
        // 设置条件格式J3-J14
        rangeAddress = new CellRangeAddress(2, 13, 9, 9);
        setConditionalFormatting(sheet, rangeAddress);

        // 设置列宽 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);
        }
    }

    /**
     * 管理端-重复投诉率
     */
    private void getSheet2(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 = getWorkbook().createSheet("管理端-重复投诉率");
        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        XSSFFont font;
        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
        // 基本模式 微软雅黑 10号字 带全边框 水平居中
        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
        font = getWorkbook().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);
        // 基础模式
        XSSFCellStyle cellStyle1 = baseStyle.copy();
        // 带边框 百分比 2位小数
        XSSFCellStyle cellStyle2 = baseStyle.copy();
        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
        // 微软雅黑 10号字 自动换行 背景色FFE7E6E6 FFAEAAAA
        XSSFCellStyle cellStyle3 = baseStyle.copy();
        // cellStyle3.setWrapText(true);
        XSSFColor color = new XSSFColor();
        color.setARGBHex("FFAEAAAA");
        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle3.setFillForegroundColor(color);

        // 第一行 标题栏
        row = sheet.createRow(0);
        cell = row.createCell(0);
        cell.setCellValue(String.format("重复投诉率（1-%s）", dayOfMonth));
        cell.setCellStyle(cellStyle3);
        // 合并单元格 A1 - G1
        rangeAddress = new CellRangeAddress(0, 0, 0, 6);
        addMergedRegion(sheet, rangeAddress);

        // 第二行
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue("工单数");
        cell.setCellStyle(cellStyle3);
        // 合并单元格 B2-C2
        rangeAddress = new CellRangeAddress(1, 1, 1, 2);
        addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(3);
        cell.setCellValue("重复投诉率");
        cell.setCellStyle(cellStyle3);
        // 合并单元格 B2-C2
        rangeAddress = new CellRangeAddress(1, 1, 3, 4);
        addMergedRegion(sheet, rangeAddress);
        cell = row.createCell(5);
        cell.setCellValue("增量");
        cell.setCellStyle(cellStyle3);
        // 合并单元格 F2-G2
        rangeAddress = new CellRangeAddress(1, 1, 5, 6);
        addMergedRegion(sheet, rangeAddress);

        // 第三行
        row = sheet.createRow(2);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(1);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(2);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(3);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(4);
        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(5);
        cell.setCellValue("工单数");
        cell.setCellStyle(cellStyle3);
        cell = row.createCell(6);
        cell.setCellValue("重复投诉率");
        cell.setCellStyle(cellStyle3);

        // 写入数据行
        List<List<Object>> sheet2Data = tslDataService.getSheet2Data(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(cellStyle1);
            // 前一天重复工单数
            cell = row.createCell(1);
            cell.setCellValue(((double) list.get(1)));
            cell.setCellStyle(cellStyle1);
            // 当天重复工单数
            cell = row.createCell(2);
            cell.setCellValue(((double) list.get(2)));
            cell.setCellStyle(cellStyle1);
            // 前一天重复投诉率
            cell = row.createCell(3);
            cell.setCellValue(((double) list.get(3)));
            cell.setCellStyle(cellStyle2);
            // 当前重复投诉率
            cell = row.createCell(4);
            cell.setCellValue(((double) list.get(4)));
            cell.setCellStyle(cellStyle2);
            // 重复工单增量
            cell = row.createCell(5);
            cell.setCellValue(((double) list.get(5)));
            cell.setCellStyle(cellStyle1);
            // 重复投诉率增量
            cell = row.createCell(6);
            cell.setCellValue(((double) list.get(6)));
            cell.setCellStyle(cellStyle2);
        }

        // 添加条件格式F4-F15
        rangeAddress = new CellRangeAddress(3, 14, 5, 5);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式G4-G15
        rangeAddress = new CellRangeAddress(3, 14, 6, 6);
        setConditionalFormatting(sheet, rangeAddress);

        // 设置列宽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);
        }
    }

    /**
     * 20230627新增 客户端-战略考核
     */
    private void getSheet1_1(String day) {
        Sheet sheet = getWorkbook().createSheet("客户端-战略考核");

        // 计算天数
        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
        int dayOfMonth = date.getDayOfMonth();

        Row row;
        Cell cell;
        CellRangeAddress rangeAddress;
        XSSFFont font;
        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();

        // 基本模式 微软雅黑 10号字 带全边框 水平居中
        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
        font = getWorkbook().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);
        // 基础模式
        XSSFCellStyle cellStyle1 = baseStyle.copy();
        // 2位小数
        XSSFCellStyle cellStyle2 = baseStyle.copy();
        cellStyle2.setDataFormat(dataFormat.getFormat("0.00"));
        // 微软雅黑 10号 加粗
        XSSFCellStyle cellStyle3 = baseStyle.copy();
        font = getWorkbook().createFont();
        font.setFontName("微软雅黑");
        font.setBold(true);
        font.setFontHeightInPoints((short) 10);
        cellStyle3.setFont(font);

        // 第一行 标题栏2023年客服投诉清单各地市投诉率情况（客户端-战略考核）
        cell = sheet.createRow(0).createCell(0);
        cell.setCellValue(day.substring(0, 4) + "年客服投诉清单各地市投诉率情况（客户端-战略考核）");
        cell.setCellStyle(cellStyle3);
        // 合并单元格
        rangeAddress = new CellRangeAddress(0, 0, 0, dayOfMonth + 7);
        sheet.addMergedRegion(rangeAddress);
        // 设置合并单元格的边框
        RegionUtil.setBorderBottom(BorderStyle.THIN, rangeAddress, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, rangeAddress, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, rangeAddress, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, rangeAddress, sheet);

        // 第二行 列名
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle1);
        for (int i = 1; i <= dayOfMonth; i++) {
            cell = row.createCell(i);
            cell.setCellValue(i + "日");
            cell.setCellStyle(cellStyle1);
        }
        cell = row.createCell(dayOfMonth + 1);
        cell.setCellValue("投诉总量");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 2);
        cell.setCellValue("用户数");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 3);
        cell.setCellValue("目前万投率");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 4);
        cell.setCellValue("本月预测");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 5);
        cell.setCellValue("目标值");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 6);
        cell.setCellValue("与目标差距");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 7);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle1);

        // 获取数据
        Map<String, List<Object>> seet1_1Data = tslDataService.getSheet1_1Data(day);

        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(cellStyle1);
            for (Object obj : seet1_1Data.get(area)) {
                cell = row.createCell(cellNum++);
                cell.setCellValue(Double.parseDouble(obj.toString()));
                cell.setCellStyle(cellStyle1);
            }
            // 写入最后一列的地市
            cell = row.createCell(cellNum);
            cell.setCellValue(area);
            cell.setCellStyle(cellStyle1);
            // cellNum复位
            cellNum = 0;
        }
        // 写入全省数据
        row = sheet.createRow(rowNum);
        // 写入A列的地市
        cell = row.createCell(cellNum++);
        cell.setCellValue("全省");
        cell.setCellStyle(cellStyle1);
        for (Object obj : seet1_1Data.get("全省")) {
            cell = row.createCell(cellNum++);
            cell.setCellValue(Double.parseDouble(obj.toString()));
            cell.setCellStyle(cellStyle1);
        }
        // 写入最后一列的地市
        cell = row.createCell(cellNum);
        cell.setCellValue("全省");
        cell.setCellStyle(cellStyle1);

        // 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(cellStyle2);
            }
        }

        // 添加条件格式B15-V15
        rangeAddress = new CellRangeAddress(rowNum, rowNum, 1, dayOfMonth);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式(dayOfMonth+3)(3-14)
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 3, dayOfMonth + 3);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式Z3-Z14
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 4, dayOfMonth + 4);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式AB3-AB14
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 6, dayOfMonth + 6);
        setConditionalFormatting(sheet, rangeAddress);

        // 设置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 getSheet1V1(String day) {
        // 获取数据
        Map<String, List<Object>> seet1Data = tslDataService.getSheet1Data(day);
        getSheet1(day, seet1Data, "管理端-移网质量类");
    }

    /**
     * 写sheet1
     */
    private void getSheet1(String day, Map<String, List<Object>> seet1Data, String sheetName) {
        Sheet sheet = getWorkbook().createSheet(sheetName);

        // 计算天数
        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
        int dayOfMonth = date.getDayOfMonth();

        Row row;
        Cell cell;

        XSSFCellStyle cellStyle1 = getWorkbook().createCellStyle();
        cellStyle1.setAlignment(HorizontalAlignment.CENTER);
        cellStyle1.setVerticalAlignment(VerticalAlignment.CENTER);
        XSSFFont font = getWorkbook().createFont();
        font.setFontName("微软雅黑");
        font.setBold(false);
        font.setFontHeightInPoints((short) 10);
        cellStyle1.setFont(font);
        cellStyle1.setBorderBottom(BorderStyle.THIN);
        cellStyle1.setBorderTop(BorderStyle.THIN);
        cellStyle1.setBorderLeft(BorderStyle.THIN);
        cellStyle1.setBorderRight(BorderStyle.THIN);
        XSSFCellStyle cellStyle3 = getWorkbook().createCellStyle();
        cellStyle3.setAlignment(HorizontalAlignment.CENTER);
        cellStyle3.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle3.setFont(font);
        cellStyle3.setBorderBottom(BorderStyle.THIN);
        cellStyle3.setBorderTop(BorderStyle.THIN);
        cellStyle3.setBorderLeft(BorderStyle.THIN);
        cellStyle3.setBorderRight(BorderStyle.THIN);
        XSSFDataFormat format = getWorkbook().createDataFormat();
        cellStyle3.setDataFormat(format.getFormat("0.00"));
        XSSFCellStyle cellStyle2 = getWorkbook().createCellStyle();
        cellStyle2.setAlignment(HorizontalAlignment.CENTER);
        cellStyle2.setVerticalAlignment(VerticalAlignment.CENTER);
        font = getWorkbook().createFont();
        font.setFontName("微软雅黑");
        font.setBold(true);
        font.setFontHeightInPoints((short) 10);
        cellStyle2.setFont(font);
        cellStyle2.setBorderBottom(BorderStyle.THIN);
        cellStyle2.setBorderTop(BorderStyle.THIN);
        cellStyle2.setBorderLeft(BorderStyle.THIN);
        cellStyle2.setBorderRight(BorderStyle.THIN);

        // 第一行 标题栏
        cell = sheet.createRow(0).createCell(0);
        cell.setCellValue(day.substring(0, 4) + "年客服投诉清单各地市投诉率情况（" + sheetName + "）");
        cell.setCellStyle(cellStyle2);
        // 合并单元格
        CellRangeAddress range = new CellRangeAddress(0, 0, 0, dayOfMonth + 7);
        sheet.addMergedRegion(range);
        // 设置合并单元格的边框
        RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);

        // 第二行 列名
        row = sheet.createRow(1);
        cell = row.createCell(0);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle1);
        for (int i = 1; i <= dayOfMonth; i++) {
            cell = row.createCell(i);
            cell.setCellValue(i + "日");
            cell.setCellStyle(cellStyle1);
        }
        cell = row.createCell(dayOfMonth + 1);
        cell.setCellValue("投诉总量");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 2);
        cell.setCellValue("用户数");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 3);
        cell.setCellValue("目前万投率");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 4);
        cell.setCellValue("本月预测");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 5);
        cell.setCellValue("目标值");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 6);
        cell.setCellValue("与目标差距");
        cell.setCellStyle(cellStyle1);
        cell = row.createCell(dayOfMonth + 7);
        cell.setCellValue("地市");
        cell.setCellStyle(cellStyle1);

        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(cellStyle1);
            for (Object obj : seet1Data.get(area)) {
                cell = row.createCell(cellNum++);
                cell.setCellValue(Double.parseDouble(obj.toString()));
                cell.setCellStyle(cellStyle1);
            }
            // 写入最后一列的地市
            cell = row.createCell(cellNum);
            cell.setCellValue(area);
            cell.setCellStyle(cellStyle1);
            // cellNum复位
            cellNum = 0;
        }
        // 写入全省数据
        row = sheet.createRow(rowNum);
        // 写入A列的地市
        cell = row.createCell(cellNum++);
        cell.setCellValue("全省");
        cell.setCellStyle(cellStyle1);
        for (Object obj : seet1Data.get("全省")) {
            cell = row.createCell(cellNum++);
            cell.setCellValue(Double.parseDouble(obj.toString()));
            cell.setCellStyle(cellStyle1);
        }
        // 写入最后一列的地市
        cell = row.createCell(cellNum);
        cell.setCellValue("全省");
        cell.setCellStyle(cellStyle1);

        // 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(cellStyle3);
            }
        }

        // 添加条件格式B15-V15
        CellRangeAddress rangeAddress = new CellRangeAddress(rowNum, rowNum, 1, dayOfMonth);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式(dayOfMonth+3)(3-14)
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 3, dayOfMonth + 3);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式Z3-Z14
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 4, dayOfMonth + 4);
        setConditionalFormatting(sheet, rangeAddress);
        // 添加条件格式AB3-AB14
        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 6, dayOfMonth + 6);
        setConditionalFormatting(sheet, rangeAddress);

        // 设置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 XSSFWorkbook getWorkbook() {
        if (workbook == null) {
            workbook = new XSSFWorkbook();
            // 基本模式 微软雅黑 10号字 带全边框 水平居中
            XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
            XSSFFont font = getWorkbook().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号字 带全边框 水平居中
            cellStyle1 = baseStyle.copy();
            // cellStyle2 百分比 2位小数
            cellStyle2 = baseStyle.copy();
            XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
            cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
            // cellStyle3 自动换行 背景色 FFAEAAAA
            cellStyle3 = baseStyle.copy();
            XSSFColor color = new XSSFColor();
            color.setARGBHex("FFAEAAAA");
            cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            cellStyle3.setFillForegroundColor(color);
        }
        return this.workbook;
    }

    /**
     * 添加合并单元格并添加边框
     */
    private void addMergedRegion(Sheet sheet, CellRangeAddress range) {
        sheet.addMergedRegion(range);
        // 设置合并单元格的边框
        RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);
    }

    /**
     * 条件格式 3色渐变 数字小的为绿色，大的为红色
     * 绿 FF63BE7B 黄 FFFFEB84 红 FFF8696B
     */
    private void setConditionalFormatting(Sheet sheet, CellRangeAddress rangeAddress) {
        SheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
        ConditionalFormattingRule rule = conditionalFormatting.createConditionalFormattingColorScaleRule();
        XSSFColor[] colors = new XSSFColor[] {
                new XSSFColor(), new XSSFColor(), new XSSFColor()
        };
        colors[0].setARGBHex("FF63BE7B");
        colors[1].setARGBHex("FFFFEB84");
        colors[2].setARGBHex("FFF8696B");
        rule.getColorScaleFormatting().setColors(colors);
        CellRangeAddress[] cellRangeAddresses = new CellRangeAddress[] {
                rangeAddress
        };
        conditionalFormatting.addConditionalFormatting(cellRangeAddresses, rule);
    }

    /**
     * 条件格式 3色渐变 数字小的为红色，大的为绿色
     * 绿 FF63BE7B 黄 FFFFEB84 红 FFF8696B
     */
    private void setConditionalFormatting2(Sheet sheet, CellRangeAddress rangeAddress) {
        SheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
        ConditionalFormattingRule rule = conditionalFormatting.createConditionalFormattingColorScaleRule();
        XSSFColor[] colors = new XSSFColor[] {
                new XSSFColor(), new XSSFColor(), new XSSFColor()
        };
        colors[0].setARGBHex("FFF8696B");
        colors[1].setARGBHex("FFFFEB84");
        colors[2].setARGBHex("FF63BE7B");
        rule.getColorScaleFormatting().setColors(colors);
        CellRangeAddress[] cellRangeAddresses = new CellRangeAddress[] {
                rangeAddress
        };
        conditionalFormatting.addConditionalFormatting(cellRangeAddresses, rule);
    }
}
