package com.ximai.mes.report.service.impl;

import com.ximai.common.utils.MessageUtils;
import com.ximai.common.utils.data.ExceptionUtil;
import com.ximai.common.utils.data.StringUtils;
import com.ximai.mes.report.mapper.DailyProductionReportMapper;
import com.ximai.mes.report.request.DailyProductionReportRequest;
import com.ximai.mes.report.service.DailyProductionReportService;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class DailyProductionReportServiceImp implements DailyProductionReportService {

    @Autowired
    DailyProductionReportMapper dailyProductionReportMapper;


    @Override
    public List getListByProcess(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map> processDataList = dailyProductionReportMapper.getListByProcess(dailyProductionReportRequest);
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        List<Map> returnList = groupList(processDataList,"工序名称","工序编码","工序",dateList);
        return returnList;
    }


    @Override
    public List getListByWorkshop(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                        && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map> processDataList = dailyProductionReportMapper.getListByWorkshop(dailyProductionReportRequest);
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        List<Map> returnList = groupList(processDataList,"车间名称","车间编码","车间",dateList);
        return returnList;
    }

    @Override
    public List getListByWorkstation(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                        && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map> processDataList = dailyProductionReportMapper.getListByWorkstation(dailyProductionReportRequest);
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        List<Map> returnList = groupList(processDataList,"工作中心名称","工作中心编码","工作中心",dateList);
        return returnList;
    }

    @Override
    public List getListByWorkunit(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                        && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map> processDataList = dailyProductionReportMapper.getListByWorkunit(dailyProductionReportRequest);
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        List<Map> returnList = groupList(processDataList,"工作单元名称","工作单元编码","工作单元",dateList);
        return returnList;
    }

    @Override
    public List getListByUser(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                        && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Map> processDataList = dailyProductionReportMapper.getListByUser(dailyProductionReportRequest);
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        List<Map> returnList = groupList(processDataList,"报工人员名称","报工人员编码","报工人员",dateList);
        return returnList;
    }

    @Override
    public List getDatas(DailyProductionReportRequest dailyProductionReportRequest) {
        ExceptionUtil.checkTrueThrowException(dailyProductionReportRequest.getStartDate() == null
                        && dailyProductionReportRequest.getEndDate() == null,
                "请传入开始和结束时间");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
        String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
        List<String> dateList = getAscDateList(startDate, endDate);
        return dateList;
    }

    public  List<String> getAscDateList(String start, String end) {

        LocalDate startDate = LocalDate.parse(start);
        LocalDate endDate = LocalDate.parse(end);
        List<String> result = new ArrayList<>();
        if (endDate.compareTo(startDate) < 0) {
            return result;
        }
        while (true) {
            result.add(startDate.toString());
            if (startDate.compareTo(endDate) >= 0) {
                break;
            }
            startDate = startDate.plusDays(1);
        }
        return result;
    }

    public List groupList(List<Map> processDataList,String name,String code,String key,List<String> dateList  ){
        Map<String,List<Map>> processDataMap = processDataList.stream().collect(Collectors.groupingBy(map -> (String)map.get(code)));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        /**
         * ［｛工序名称：abc，工序编码：cbd,工序总结：1，日期a：｛合格数｝｝］
         */
        List<Map> returnList = new ArrayList<>();
        for (String processCode : processDataMap.keySet()){
            HashMap processHashMap = new HashMap();
            returnList.add(processHashMap);
            processHashMap.put(code,processCode);
            processHashMap.put(name,processDataMap.get(processCode).get(0).get(name));
            processHashMap.put(key + "统计合格数量", new Double(0));
            processHashMap.put(key + "统计不合格数量",new Double(0));
            processHashMap.put(key + "统计报工数量",new Double(0));
            Map<String,List<Map>> dateDataMap = processDataMap.get(processCode).stream().collect(Collectors.groupingBy(map -> (String)map.get("报工日期")));
            for (String date : dateList){
                HashMap dateHashMap = new HashMap();
                processHashMap.put(date,dateHashMap);
                if(dateDataMap.get(date) != null){
                    for (Map data : dateDataMap.get(date)){
                        //PS这里其实做多只有一条Map data
                        dateHashMap.put("合格数量",data.get("合格数量"));
                        dateHashMap.put("不合格数量",data.get("不合格数量"));
                        dateHashMap.put("报工数量",data.get("报工数量"));
                        dateHashMap.put("合格率",(new BigDecimal((Double) data.get("合格数量")).multiply(new BigDecimal(100))).divide( new BigDecimal((Double) data.get("报工数量")),2, RoundingMode.HALF_UP));
                        processHashMap.put(key + "统计合格数量", ((Double)processHashMap.get(key + "统计合格数量")) + ((Double)data.get("合格数量")));
                        processHashMap.put(key + "统计不合格数量",((Double)processHashMap.get(key + "统计不合格数量")) + ((Double)data.get("不合格数量")));
                        processHashMap.put(key + "统计报工数量",((Double)processHashMap.get(key + "统计报工数量")) + ((Double)data.get("报工数量")));
                    }
                }
            }
            if(((Double)processHashMap.get(key + "统计报工数量")) > 0){
                processHashMap.put(key + "统计合格率",(new BigDecimal((Double) processHashMap.get(key + "统计合格数量")).multiply(new BigDecimal(100))).divide(new BigDecimal((Double)processHashMap.get(key + "统计报工数量")),2, RoundingMode.HALF_UP));
            }else{
                processHashMap.put(key + "统计合格率",BigDecimal.ZERO);

            }
        }


        //用于统计最后一行的日期综合统计性数据
        Map<String,List<Map>> dateDataMap = processDataList.stream().collect(Collectors.groupingBy(map -> (String)map.get("报工日期")));
        HashMap dateHashMap = new HashMap();
        dateHashMap.put(key + "统计合格数量", new Double(0));
        dateHashMap.put(key + "统计不合格数量",new Double(0));
        dateHashMap.put(key + "统计报工数量",new Double(0));
        for (Map data : returnList){
            dateHashMap.put(key + "统计合格数量", (Double)dateHashMap.get(key + "统计合格数量") + (Double)data.get(key + "统计合格数量"));
            dateHashMap.put(key + "统计不合格数量", (Double)dateHashMap.get(key + "统计不合格数量") + (Double)data.get(key + "统计不合格数量"));
            dateHashMap.put(key + "统计报工数量", (Double)dateHashMap.get(key + "统计报工数量") + (Double)data.get(key + "统计报工数量"));
        }
        if(((Double)dateHashMap.get(key + "统计报工数量")) > 0){
            dateHashMap.put(key + "统计合格率",(new BigDecimal((Double) dateHashMap.get(key + "统计合格数量")).multiply(new BigDecimal(100))).divide(new BigDecimal((Double)dateHashMap.get(key + "统计报工数量")),2, RoundingMode.HALF_UP));
        }else{
            dateHashMap.put(key + "统计合格率",BigDecimal.ZERO);
        }
        returnList.add(dateHashMap);
        for (String date : dateList){
            HashMap dateStatisticsHashMap = new HashMap();
            dateHashMap.put(date,dateStatisticsHashMap);
            dateStatisticsHashMap.put("日期统计合格数量", new Double(0));
            dateStatisticsHashMap.put("日期统计不合格数量",new Double(0));
            dateStatisticsHashMap.put("日期统计报工数量",new Double(0));
            if(dateDataMap.get(date) != null){
                for (Map data : dateDataMap.get(date)){
                    dateStatisticsHashMap.put("日期统计合格数量", ((Double)dateStatisticsHashMap.get("日期统计合格数量")) + ((Double)data.get("合格数量")));
                    dateStatisticsHashMap.put("日期统计不合格数量",((Double)dateStatisticsHashMap.get("日期统计不合格数量")) + ((Double)data.get("不合格数量")));
                    dateStatisticsHashMap.put("日期统计报工数量",((Double)dateStatisticsHashMap.get("日期统计报工数量")) + ((Double)data.get("报工数量")));
                }
            }

            if(((Double)dateStatisticsHashMap.get("日期统计报工数量")) > 0){
                dateStatisticsHashMap.put("日期统计合格率",
                        new BigDecimal((Double)dateStatisticsHashMap.get("日期统计合格数量")).multiply(new BigDecimal(100)).divide(new BigDecimal((Double)dateStatisticsHashMap.get("日期统计报工数量")),2, RoundingMode.HALF_UP));
            }else{
                dateStatisticsHashMap.put("日期统计合格率",BigDecimal.ZERO);
            }
        }


        return returnList;
    }











    public void export(HttpServletResponse response,List<Map> returnList,String filename,String name,String code,String key, List<String> dataList){
        // 第一步，创建一个Workbook，对应一个Excel文件
        XSSFWorkbook wb = new XSSFWorkbook();
        // 第二步，在Workbook中添加一个sheet,对应Excel文件中的sheet
        XSSFSheet sheet = wb.createSheet("sheet");
        // 第三步，设置样式以及字体样式
        XSSFCellStyle titleStyle = createTitleCellStyle(wb);
        XSSFCellStyle headerStyle = createHeadCellStyle(wb);
        XSSFCellStyle contentStyle = createContentCellStyle(wb);
        if(returnList.size() > 0){
            // 在工作表中合并单元格，合并第一行的前两个单元格
            CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 1, 0, 0); // 参数依次是：开始行，结束行，开始列，结束列
            CellRangeAddress cellRangeAddressb = new CellRangeAddress(0, 1, 1, 1);
            sheet.addMergedRegion(cellRangeAddress);
            sheet.addMergedRegion(cellRangeAddressb);
            // 创建第一页的第一行，索引从0开始
            XSSFRow row0 = sheet.createRow(0);
            XSSFRow row1 = sheet.createRow(1);
            // 设置列宽
            XSSFCell r0c0 = row0.createCell(0);
            r0c0.setCellValue(code);
            r0c0.setCellStyle(headerStyle);
            row0.setHeight((short) 600);
            XSSFCell r1c0 = row1.createCell(0);
            r1c0.setCellStyle(headerStyle);
            XSSFCell r0c1 = row0.createCell(1);
            r0c1.setCellValue(name);
            r0c1.setCellStyle(headerStyle);
            XSSFCell r1c1 = row1.createCell(1);
            r1c1.setCellStyle(headerStyle);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//            String startDate = simpleDateFormat.format(dailyProductionReportRequest.getStartDate());
//            String endDate = simpleDateFormat.format(dailyProductionReportRequest.getEndDate());
//
//            List<String> dataList = getAscDateList(startDate, endDate);
            for (int size = 0 ; size < dataList.size() * 4 + 6 ; size ++){
                sheet.setColumnWidth(size ,3000);
            }
            int i = 2;
            int x = 0;
            for (String date : dataList){
                x++;
                //设置日期
                CellRangeAddress cellAddresses = new CellRangeAddress(0, 0, i, i +3);
                sheet.addMergedRegion(cellAddresses);
                XSSFCell r0i = row0.createCell(i);
                r0i.setCellValue(date);
                r0i.setCellStyle(headerStyle);
                //设置日期下的字段
                XSSFCell r1i = row1.createCell(i);
                r1i.setCellValue("统计报工数量");
                r1i.setCellStyle(headerStyle);
                XSSFCell r1i1 = row1.createCell(i+1);
                r1i1.setCellValue("统计合格数量");
                r1i1.setCellStyle(headerStyle);
                XSSFCell r1i2 = row1.createCell(i+2);
                r1i2.setCellValue("统计不合格数量");
                r1i2.setCellStyle(headerStyle);
                XSSFCell r1i3 = row1.createCell(i+3);
                r1i3.setCellValue("统计合格率");
                r1i3.setCellStyle(headerStyle);
                i = i + 4;
                //末尾累加统计
                if(dataList.size() == x){
                    //设置日期
                    CellRangeAddress cellAddressesOver = new CellRangeAddress(0, 0, i, i +3);
                    sheet.addMergedRegion(cellAddressesOver);
                    XSSFCell r0iOver = row0.createCell(i);
                    r0iOver.setCellValue("合计");
                    r0iOver.setCellStyle(headerStyle);
                    //设置日期下的字段
                    XSSFCell r1iOver = row1.createCell(i);
                    r1iOver.setCellValue("报工数量");
                    r1iOver.setCellStyle(headerStyle);
                    XSSFCell r1i1Over = row1.createCell(i+1);
                    r1i1Over.setCellValue("合格数量");
                    r1i1Over.setCellStyle(headerStyle);
                    XSSFCell r1i2Over = row1.createCell(i+2);
                    r1i2Over.setCellValue("不合格数量");
                    r1i2Over.setCellStyle(headerStyle);
                    XSSFCell r1i3Over = row1.createCell(i+3);
                    r1i3Over.setCellValue("合格率%");
                    r1i3Over.setCellStyle(headerStyle);
                }
            }





            for (int t = 0 ; t< returnList.size() ; t++){
                Map rowData = returnList.get(t);
                //处理头部两列
                XSSFRow rt = sheet.createRow(2+t);
                XSSFCell ri0 = rt.createCell(0);
                XSSFCell ri1 = rt.createCell(1);
                ri0.setCellStyle(contentStyle);
                ri1.setCellStyle(contentStyle);
                String rowDataCode = (String)rowData.get(code);
                if(StringUtils.isEmpty(rowDataCode)){
                    ri0.setCellValue("合计");
                }else{
                    ri0.setCellValue((String)rowData.get(code));

                    ri1.setCellValue((String)rowData.get(name));
                }
                //处理尾部四列
                XSSFCell rtSize2 =  rt.createCell((dataList.size() * 4)+2);
                rtSize2.setCellValue((Double) rowData.get(key+"统计报工数量"));
                rtSize2.setCellStyle(contentStyle);
                XSSFCell rtSize3 = rt.createCell((dataList.size() * 4)+3);
                rtSize3.setCellValue((Double) rowData.get(key+"统计合格数量"));
                rtSize3.setCellStyle(contentStyle);
                XSSFCell rtSize4 = rt.createCell((dataList.size() * 4)+4);
                rtSize4.setCellValue((Double) rowData.get(key+"统计不合格数量"));
                rtSize4.setCellStyle(contentStyle);
                XSSFCell rtSize5 = rt.createCell((dataList.size() * 4)+5);
                rtSize5.setCellValue(((BigDecimal) rowData.get(key+"统计合格率")).doubleValue());
                rtSize5.setCellStyle(contentStyle);
                //处理中间
                for (int size = 0 ;size < dataList.size() ; size ++){
                    String date = dataList.get(size);
                    int updateSize = updateSize = size * 4;
                    XSSFCell rti2 =  rt.createCell(updateSize+2);
                    rti2.setCellStyle(contentStyle);
                    XSSFCell rti3 = rt.createCell(updateSize+3);
                    rti3.setCellStyle(contentStyle);
                    XSSFCell rti4 = rt.createCell(updateSize+4);
                    rti4.setCellStyle(contentStyle);
                    XSSFCell rti5 = rt.createCell(updateSize+5);
                    rti5.setCellStyle(contentStyle);
                    Map dateData = (Map) rowData.get(date);
                    if(dateData.isEmpty()){
                        rti2.setCellValue(0);
                        rti3.setCellValue(0);
                        rti4.setCellValue(0);
                        rti5.setCellValue(0);
                    }else{
                        //
                        Double feedback = (Double) dateData.get("报工数量");
                        Double unqualify = (Double) dateData.get("不合格数量");
                        Double qualify = (Double) dateData.get("合格数量");
                        BigDecimal fee = (BigDecimal) dateData.get("合格率");
                        if(feedback == null){
                            feedback = (Double) dateData.get("日期统计报工数量");
                            unqualify = (Double) dateData.get("日期统计不合格数量");
                            qualify = (Double) dateData.get("日期统计合格数量");
                            fee = (BigDecimal) dateData.get("日期统计合格率");
                        }
                        rti2.setCellValue(feedback);
                        rti3.setCellValue(qualify);
                        rti4.setCellValue(unqualify);
                        rti5.setCellValue(fee.doubleValue());
                    }
                }

//            XSSFCell rti = rt.createCell(i);
//            rti.setCellValue(i);
//            rti.setCellStyle(contentStyle);
//            XSSFCell rti1 = rt.createCell(i+1);
//            rti1.setCellValue(i+1);
//            rti1.setCellStyle(contentStyle);
//            XSSFCell rti2 = rt.createCell(i+2);
//            rti2.setCellValue(i+2);
//            rti2.setCellStyle(contentStyle);
//            XSSFCell rti3 = rt.createCell(i+3);
//            rti3.setCellValue(i+3);
//            rti3.setCellStyle(contentStyle);




            }
        }




        buildExcelDocument(filename+".xlsx", wb, response);
    }
    /**
     * 创建标题样式
     *
     * @param wb
     * @return
     */
    private static XSSFCellStyle createTitleCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//        cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());//背景颜色

        XSSFFont headerFont1 = (XSSFFont) wb.createFont(); // 创建字体样式
        headerFont1.setBold(true); //字体加粗
        headerFont1.setFontName("黑体"); // 设置字体类型
        headerFont1.setFontHeightInPoints((short) 15); // 设置字体大小
        cellStyle.setFont(headerFont1); // 为标题样式设置字体样式
        return cellStyle;
    }

    /**
     * 创建表头样式
     *
     * @param wb
     * @return
     */
    private static XSSFCellStyle createHeadCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//背景颜色
        cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直对齐
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        XSSFFont headerFont = (XSSFFont) wb.createFont(); // 创建字体样式
        headerFont.setBold(true); //字体加粗
        headerFont.setFontName("黑体"); // 设置字体类型
        headerFont.setFontHeightInPoints((short) 12); // 设置字体大小
        cellStyle.setFont(headerFont); // 为标题样式设置字体样式

        return cellStyle;
    }

    /**
     * 创建内容样式
     *
     * @param wb
     * @return
     */
    private static XSSFCellStyle createContentCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        // 生成12号字体
        XSSFFont font = wb.createFont();
        font.setColor((short) 8);
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);

        return cellStyle;
    }







    private static void buildExcelDocument(String fileName, Workbook wb, HttpServletResponse response) {
        try {
            response.setContentType("application/octet-stream");
            // 可自行定义编码格式
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            //清除jsp编译html文件的空白,防止excel出现空行
            response.flushBuffer();
            //写出
            wb.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(wb);
        }
    }



}
