package com.jjt.biz.controller;

import com.jjt.common.core.controller.BaseController;
import com.jjt.common.utils.DateUtils;
import com.jjt.emp.domain.TwinEmpCalc;
import com.jjt.emp.service.ITwinEmpCalcService;
import com.jjt.utils.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Excel导出控制类
 *
 * @author ruoyi
 */
@Api(tags = "数据导出接口--绩效")
@RestController
@Slf4j
public class ApiProductivityExportController extends BaseController {
    @Resource
    private ITwinEmpCalcService empCalcService;

    @ApiOperation("导出绩效日报")
    @RequestMapping("/api/export/productivity-day")
    @CrossOrigin(origins = "*")
    public void productivityDayExport(String date, HttpServletResponse response) {
        LocalDate localDate = LocalDate.parse(date);
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/productivity-day.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
            CreationHelper creationHelper = wb.getCreationHelper();
            CellStyle percentStyle = wb.createCellStyle();
            percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
            percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            CellStyle p2 = wb.createCellStyle();
            p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
            XSSFCellStyle bk = wb.createCellStyle();
            bk.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
            bk.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            XSSFCellStyle bkp = wb.createCellStyle();
            bkp.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
            bkp.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            bkp.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
            bkp.setVerticalAlignment(VerticalAlignment.CENTER);

            List<TwinEmpCalc> list = empCalcService.selectTwinEmpCalcListByDate(DateUtils.parseDate(date));
            Sheet sheet = wb.getSheetAt(0);
            Sheet bSheet = wb.cloneSheet(0);
            Cell title = sheet.getRow(0).getCell(0);
            title.setCellValue("A班经编生产绩效日报（" + date + "）");
            Cell bTitle = bSheet.getRow(0).getCell(0);
            bTitle.setCellValue("B班经编生产绩效日报（" + date + "）");
            //按姓名分组
            Map<String, List<TwinEmpCalc>> mapA = list.stream().filter(o -> "A".equals(o.getEmpTeam())).collect(Collectors.groupingBy(TwinEmpCalc::getEmpName, LinkedHashMap::new, Collectors.toList()));
            Map<String, List<TwinEmpCalc>> mapB = list.stream().filter(o -> "B".equals(o.getEmpTeam())).collect(Collectors.groupingBy(TwinEmpCalc::getEmpName, LinkedHashMap::new, Collectors.toList()));
            processJx(sheet, mapA, percentStyle, p2, bk, bkp);

            processJx(bSheet, mapB, percentStyle, p2, bk, bkp);
            wb.setSheetName(0, "A班经编生产绩效");
            wb.setSheetName(1, "B班经编生产绩效");

            // 清空response
            response.reset();
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            //Content-Disposition的作用：告知浏览器以何种方式显示响应返回的文件，用浏览器打开还是以附件的形式下载到本地保存
            //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
            // filename表示文件的默认名称，因为网络传输只支持URL编码的相关支付，因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("经编生产绩效日报" + localDate + ".xlsx", "UTF-8"));
            response.setContentType("application/octet-stream");
            wb.write(outputStream);
            outputStream.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @ApiOperation("导出绩效月报")
    @RequestMapping("/api/export/productivity-month")
    @CrossOrigin(origins = "*")
    public void productivityMonthExport(String date, HttpServletResponse response) {
        date = date.substring(0, 7);
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/productivity-month.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
            CreationHelper creationHelper = wb.getCreationHelper();
            CellStyle percentStyle = wb.createCellStyle();
            percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
            percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            CellStyle p2 = wb.createCellStyle();
            p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
            XSSFCellStyle bk = wb.createCellStyle();
            bk.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
            bk.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            List<TwinEmpCalc> list = empCalcService.selectTwinEmpCalcListByMonth(date);
            Sheet sheet = wb.getSheetAt(0);
            Cell title = sheet.getRow(0).getCell(0);
            title.setCellValue("经编生产绩效月报（" + date + "）");
            //1.按姓名分组
            Map<String, List<TwinEmpCalc>> map = list.stream().collect(Collectors.groupingBy(TwinEmpCalc::getEmpName, LinkedHashMap::new, Collectors.toList()));
            int rowNum = 3;
            for (String name : map.keySet()) {
                int sr = rowNum;
                List<TwinEmpCalc> calcList = map.get(name);
                //密度字段合并
                calcList.forEach(calc -> calc.setDensity(Tools.density(calc.getDensity())));
                //2.按密度分组
                Map<BigDecimal, List<TwinEmpCalc>> densityMap = calcList.stream().collect(Collectors.groupingBy(TwinEmpCalc::getDensity, LinkedHashMap::new, Collectors.toList()));
                BigDecimal[] dayCalc = new BigDecimal[31];
                BigDecimal totalP = BigDecimal.ZERO;
                Arrays.fill(dayCalc, BigDecimal.ZERO);
                for (BigDecimal density : densityMap.keySet()) {
                    BigDecimal totalLength = BigDecimal.ZERO;
                    List<TwinEmpCalc> tempList = densityMap.get(density);
                    Row row = sheet.createRow(rowNum);
                    Cell[] cells = new Cell[36];
                    for (int i = 0; i < cells.length; i++) {
                        cells[i] = row.createCell(i);
                    }
                    cells[0].setCellValue(name);
                    cells[1].setCellValue(density.doubleValue());
                    cells[1].setCellStyle(bk);
                    BigDecimal[] lengths = new BigDecimal[31];
                    Arrays.fill(lengths, BigDecimal.ZERO);
                    BigDecimal price = BigDecimal.ZERO;
                    for (TwinEmpCalc calc : tempList) {
                        int day = DateUtils.toLocalDate(calc.getEmpDate()).getDayOfMonth();
                        lengths[day - 1] = lengths[day - 1].add(calc.getLength());
                        dayCalc[day - 1] = dayCalc[day - 1].add(calc.getLength());
                        totalLength = totalLength.add(calc.getLength());
                        if (calc.getPrice() != null) {
                            price = calc.getPrice();
                        }
                    }
                    for (int i = 0; i < lengths.length; i++) {
                        if (lengths[i].compareTo(BigDecimal.ZERO) != 0) {
                            cells[i + 2].setCellValue(lengths[i].doubleValue());
                        }
                    }
                    cells[33].setCellValue(totalLength.doubleValue());
                    BigDecimal totalPrice = totalLength.multiply(price);
                    totalP = totalP.add(totalPrice);
                    cells[34].setCellValue(price.doubleValue());
                    cells[35].setCellValue(totalPrice.doubleValue());
                    rowNum++;
                }

                Row row = sheet.createRow(rowNum);
                Cell[] cells = new Cell[36];
                for (int i = 0; i < cells.length; i++) {
                    cells[i] = row.createCell(i);
                }
                cells[0].setCellValue(name);
                cells[1].setCellValue("合计");
                cells[1].setCellStyle(bk);
                BigDecimal total = BigDecimal.ZERO;
                for (int i = 0; i < dayCalc.length; i++) {
                    if (dayCalc[i].compareTo(BigDecimal.ZERO) != 0) {
                        cells[i + 2].setCellValue(dayCalc[i].doubleValue());
                        total = total.add(dayCalc[i]);
                    }
                    cells[i + 2].setCellStyle(bk);
                }
                cells[33].setCellValue(total.doubleValue());
                cells[33].setCellStyle(bk);
                cells[34].setCellValue("合计：");
                cells[34].setCellStyle(bk);
                cells[35].setCellValue(totalP.doubleValue());
                cells[35].setCellStyle(bk);
                int er = rowNum;
                sheet.addMergedRegion(new CellRangeAddress(sr, er, 0, 0));
                rowNum++;
            }
            // 清空response
            response.reset();
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            //Content-Disposition的作用：告知浏览器以何种方式显示响应返回的文件，用浏览器打开还是以附件的形式下载到本地保存
            //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
            // filename表示文件的默认名称，因为网络传输只支持URL编码的相关支付，因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("经编生产绩效月报" + date + ".xlsx", "UTF-8"));
            response.setContentType("application/octet-stream");
            wb.write(outputStream);
            outputStream.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


    private void processJx(Sheet sheet, Map<String, List<TwinEmpCalc>> map, CellStyle percentStyle, CellStyle p2, XSSFCellStyle bk, XSSFCellStyle bkp) {
        int rowNum = 2;
        for (String name : map.keySet()) {
            List<TwinEmpCalc> calcList = map.get(name);
            Map<Long, List<TwinEmpCalc>> calcMap = calcList.stream().collect(Collectors.groupingBy(TwinEmpCalc::getDeviceId, LinkedHashMap::new, Collectors.toList()));
            int sr = rowNum;
            BigDecimal len = BigDecimal.ZERO;
            BigDecimal total = BigDecimal.ZERO;
            BigDecimal ef = BigDecimal.ZERO;
            for (Long deviceId : calcMap.keySet()) {
                List<TwinEmpCalc> list = calcMap.get(deviceId);
                int ssr = rowNum;
                for (TwinEmpCalc calc : list) {
                    Row row = sheet.createRow(rowNum);
                    Cell[] cells = new Cell[10];
                    for (int i = 0; i < cells.length; i++) {
                        cells[i] = row.createCell(i);
                    }
                    cells[0].setCellValue(name);
                    cells[1].setCellValue(calc.getDeviceId());
                    if (ssr == rowNum) {
                        cells[2].setCellValue(calc.getEfficiency().setScale(4, RoundingMode.HALF_UP).doubleValue());
                        cells[2].setCellStyle(percentStyle);
                        ef = ef.add(calc.getEfficiency());
                    }
//                    cells[3].setCellValue();
                    if (calc.getHeight() != null) {
                        cells[4].setCellValue(calc.getHeight().setScale(2, RoundingMode.HALF_UP).doubleValue());
                    }
                    cells[5].setCellValue(calc.getMick());
                    cells[6].setCellValue(calc.getDensity().setScale(2, RoundingMode.HALF_UP).doubleValue());
                    cells[6].setCellStyle(p2);
                    cells[7].setCellValue(calc.getLength().doubleValue());
                    len = len.add(calc.getLength());
                    if (calc.getPrice() != null) {
                        BigDecimal totalPrice = calc.getTotalPrice().setScale(2, RoundingMode.HALF_UP);
                        total = total.add(totalPrice);
                        cells[8].setCellValue(calc.getPrice().doubleValue());
                        cells[9].setCellValue(totalPrice.doubleValue());
                    }
                    rowNum++;
                }
                int eer = rowNum - 1;
                if (list.size() > 1) {
                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, 1, 1));
                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, 2, 2));
                }
            }
            Cell[] cells = new Cell[10];
            Row row = sheet.createRow(rowNum);
            for (int i = 0; i < cells.length; i++) {
                cells[i] = row.createCell(i);
                cells[i].setCellStyle(bk);
            }
            BigDecimal avgEf = ef.divide(BigDecimal.valueOf(calcMap.size()), 4, RoundingMode.HALF_UP);
            cells[0].setCellValue(name);
            cells[1].setCellValue("合计");
            cells[2].setCellValue(avgEf.doubleValue());
            cells[2].setCellStyle(bkp);
            cells[7].setCellValue(len.doubleValue());
            cells[9].setCellValue(total.doubleValue());
            rowNum++;

            int er = rowNum - 1;
            sheet.addMergedRegion(new CellRangeAddress(sr, er, 0, 0));
        }
    }
}
