package com.ywt.mg.web.common;

import com.ywt.mg.core.exceptions.AppMessageException;
import com.ywt.mg.core.utils.Checker;
import com.ywt.mg.core.utils.ExcelHelper;
import com.ywt.mg.domain.models.ExcelDataMap;
import com.ywt.mg.domain.models.ExcelStyleMap;
import com.ywt.mg.domain.models.pojo.CustomExcelItem;
import com.ywt.mg.domain.models.pojo.ExcelCollectPojo;
import jxl.Workbook;
import jxl.format.*;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.VerticalAlignment;
import jxl.write.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author daiyihua
 * @create 2022-08-23 下午3:52
 * @desc excel 下载里面抽出来的一些代码
 **/

@Service
public class ExcelDownloadSrv {
    private final Logger logger = LoggerFactory.getLogger(getClass().getName());

    /**
     * 下载excel 时 设置 httpServletResponse
     */
    public static HttpServletResponse setHttpServletResponse(HttpServletResponse httpServletResponse, String filename) throws IOException {
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(), "iso-8859-1"));
        httpServletResponse.setContentType("application/vnd.ms-excel;charset=UTF-8");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setHeader("Cache-Control", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        return httpServletResponse;
    }

    /**
     * 得到已经设置好的excel模版
     *
     * @return
     */
    public static WritableCellFormat getWritableCellFormat() throws WriteException {
        //设置字体;
        WritableFont font = new WritableFont(WritableFont.ARIAL, 14, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK);

        WritableCellFormat cellFormat = new WritableCellFormat(font);
        //设置背景颜色;
        cellFormat.setBackground(Colour.WHITE);
        //设置边框;
        cellFormat.setBorder(Border.ALL, BorderLineStyle.DASH_DOT);
        //设置自动换行;
        cellFormat.setWrap(true);
        //设置文字居中对齐方式;
        cellFormat.setAlignment(Alignment.CENTRE);
        //设置垂直居中;
        cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        return cellFormat;
    }

    /**
     * 通用的生成 Excel 文件并以流返回
     *
     * @param fileName            excel 文件名
     * @param data                需要填充的数据，key 是列名，value 是每一列的数据组成的 list, 类型必须是 {@link String}
     * @param httpServletResponse resp
     * @throws AppMessageException 业务层异常抛出，如传入数据为空
     * @author Walker, added on 06/27/2019.
     */
    public void generateAndReturnExcelFile(String fileName, ExcelDataMap data, ExcelStyleMap excelStyleMap,
                                           HttpServletResponse httpServletResponse) throws AppMessageException {
        if (data == null || data.isEmpty()) {
            throw new AppMessageException("数据为空");
        }
        try (OutputStream out = ExcelDownloadSrv.setHttpServletResponse(httpServletResponse, fileName + ".xls").getOutputStream()) {
            // 创建写工作簿对象
            WritableWorkbook workbook = Workbook.createWorkbook(out);
            // 工作表
            WritableSheet sheet = workbook.createSheet(fileName, 0);
            //表头格式
            WritableCellFormat cellFormat = ExcelDownloadSrv.getWritableCellFormat();
            //数据行格式
            // 设置背景、字体颜色、对齐方式等等;
            WritableFont font2 = new WritableFont(WritableFont.ARIAL, 14, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
            WritableCellFormat cellFormat2 = new WritableCellFormat(font2);
            //设置文字居中对齐方式;
            cellFormat2.setAlignment(Alignment.CENTRE);
            //设置垂直居中;
            cellFormat2.setVerticalAlignment(VerticalAlignment.CENTRE);
            cellFormat2.setBackground(Colour.WHITE);
            cellFormat2.setBorder(Border.ALL, BorderLineStyle.THIN);
            cellFormat2.setWrap(true);
            //给sheet电子版中所有的列设置默认的列的宽度;
            sheet.getSettings().setDefaultColumnWidth(20);
            sheet.getSettings().setDefaultRowHeight(30 * 20);

            //单独应用样式
            if (excelStyleMap != null) {
                for (String column : excelStyleMap.keySet()) {
                    // 指定列宽
                    int styleColumnWidth = excelStyleMap.getIntValueSafely(column, ExcelStyleMap.STYLE_COLUMN_WIDTH, 0);
                    List<String> columns = new ArrayList<>(data.keySet());
                    for (int i = 0; i < columns.size(); i++) {
                        if (columns.get(i).equals(column)) {
                            sheet.setColumnView(i, styleColumnWidth);
                        }
                    }
                }
            }

            //行号
            int firstRow = 0;
            //填充表头
            int headerColumn = 0;
            for (String key : data.keySet()) {
                Label label = new Label(headerColumn, firstRow, key, cellFormat);
                sheet.addCell(label);
                List<String> colData = data.get(key);
                for (int i = 0; i < colData.size(); i++) {
                    Label lb = new Label(headerColumn, i + 1, Checker.getStringValue(colData.get(i)), cellFormat2);
                    sheet.addCell(lb);
                }
                headerColumn++;
            }
            //开始执行写入操作
            workbook.write();
            //关闭流
            workbook.close();
        } catch (Exception e) {
            logger.error("ExcelDownloadSrv#generateAndReturnExcelFile(fileName={}):\n {}",
                    fileName, e.getMessage(), e);
        }
    }

    /**
     * 通用的生成 Excel 文件并以流返回
     *
     * @param fileName            excel 文件名
     * @param data                需要填充的数据，key 是列名，value 是每一列的数据组成的 list, 类型必须是 {@link String}
     * @param httpServletResponse resp
     * @throws AppMessageException 业务层异常抛出，如传入数据为空
     * @author Walker, added on 06/27/2019.
     */
    public void generateAndReturnExcelFileWithNoStyle(String fileName, ExcelDataMap data, ExcelStyleMap excelStyleMap,
                                                      HttpServletResponse httpServletResponse) throws AppMessageException {
        if (data == null || data.isEmpty()) {
            throw new AppMessageException("数据为空");
        }
        try (OutputStream out = ExcelDownloadSrv.setHttpServletResponse(httpServletResponse, fileName + ".xls").getOutputStream()) {
            // 创建写工作簿对象
            WritableWorkbook workbook = Workbook.createWorkbook(out);
            // 工作表
            WritableSheet sheet = workbook.createSheet(fileName, 0);

            //单独应用样式
            if (excelStyleMap != null) {
                for (String column : excelStyleMap.keySet()) {
                    // 指定列宽
                    int styleColumnWidth = excelStyleMap.getIntValueSafely(column, ExcelStyleMap.STYLE_COLUMN_WIDTH, 0);
                    List<String> columns = new ArrayList<>(data.keySet());
                    for (int i = 0; i < columns.size(); i++) {
                        if (columns.get(i).equals(column)) {
                            sheet.setColumnView(i, styleColumnWidth);
                        }
                    }
                }
            }

            //行号
            int firstRow = 0;
            //填充表头
            int headerColumn = 0;
            for (String key : data.keySet()) {
                Label label = new Label(headerColumn, firstRow, key);
                sheet.addCell(label);
                List<String> colData = data.get(key);
                for (int i = 0; i < colData.size(); i++) {
                    Label lb = new Label(headerColumn, i + 1, Checker.getStringValue(colData.get(i)));
                    sheet.addCell(lb);
                }
                headerColumn++;
            }
            //开始执行写入操作
            workbook.write();
            //关闭流
            workbook.close();
        } catch (Exception e) {
            logger.error("ExcelDownloadSrv#generateAndReturnExcelFile(fileName={} ):\n {}",
                    fileName, e.getMessage(), e);
        }
    }

    /**
     * 通用的生成 Excel 文件(包含汇总)并以流返回
     *
     * @param fileName            excel 文件名
     * @param data                需要填充的数据，key 是列名，value 是每一列的数据组成的 list, 类型必须是 {@link String}
     * @param httpServletResponse resp
     * @throws AppMessageException 业务层异常抛出，如传入数据为空
     * @author Walker, added on 06/27/2019.
     */
    public void generateAndReturnExcelFileWithNoStyleAndCollect(String fileName, ExcelDataMap data, ExcelStyleMap excelStyleMap,
                                                                List<ExcelCollectPojo> collectList, HttpServletResponse httpServletResponse) throws AppMessageException {
        if (data == null || data.isEmpty()) {
            throw new AppMessageException("数据为空");
        }
        try (OutputStream out = ExcelDownloadSrv.setHttpServletResponse(httpServletResponse, fileName + ".xls").getOutputStream()) {
            // 创建写工作簿对象
            WritableWorkbook workbook = Workbook.createWorkbook(out);
            // 工作表
            WritableSheet sheet = workbook.createSheet(fileName, 0);
            //单独应用样式
            if (excelStyleMap != null) {
                for (String column : excelStyleMap.keySet()) {
                    // 指定列宽
                    int styleColumnWidth = excelStyleMap.getIntValueSafely(column, ExcelStyleMap.STYLE_COLUMN_WIDTH, 0);
                    List<String> columns = new ArrayList<>(data.keySet());
                    for (int i = 0; i < columns.size(); i++) {
                        if (columns.get(i).equals(column)) {
                            sheet.setColumnView(i, styleColumnWidth);
                        }
                    }
                }
            }
            // 设置格式(实线)
            WritableCellFormat cellFormat = ExcelHelper.getThinWritableCellFormat();
            //给sheet电子版中所有的列设置默认的列的宽度;
            sheet.getSettings().setDefaultColumnWidth(20);
            sheet.getSettings().setDefaultRowHeight(35 * 20);
            //行号
            int firstRow = 0;
            //填充表头
            int headerColumn = 0;
            for (String key : data.keySet()) {
                Label label = new Label(headerColumn, firstRow, key, cellFormat);
                sheet.addCell(label);
                List<String> colData = data.get(key);
                for (int i = 0; i < colData.size(); i++) {
                    Label lb = new Label(headerColumn, i + 1, Checker.getStringValue(colData.get(i)), cellFormat);
                    sheet.addCell(lb);
                }
                headerColumn++;
            }
            // 添加汇总
            if (!Checker.isNone(collectList)) {
                for (ExcelCollectPojo pojo : collectList) {
                    String[] dataArr = pojo.getDataArr();
                    for (int i = 0, j = dataArr.length; i < j; i++) {
                        Label lb = new Label(pojo.getCol() + i, pojo.getRow(), dataArr[i], cellFormat);
                        sheet.addCell(lb);
                    }
                }
            }

            //开始执行写入操作
            workbook.write();
            //关闭流
            workbook.close();
        } catch (Exception e) {
            logger.error("ExcelDownloadSrv#generateAndReturnExcelFile(fileName={} ):\n {}",
                    fileName, e.getMessage(), e);
        }
    }

    /**
     * 通用的生成 Excel 文件(包含汇总)并以流返回(一点样式也没有)
     *
     * @param fileName            excel 文件名
     * @param data                需要填充的数据，key 是列名，value 是每一列的数据组成的 list, 类型必须是 {@link String}
     * @throws AppMessageException 业务层异常抛出，如传入数据为空
     * @author Walker, added on 06/27/2019.
     */
    public OutputStream  generateAndReturnExcelFileWithNoStyleAndCollectLocal(String fileName, String path, ExcelDataMap data, ExcelStyleMap excelStyleMap,
                                                                       List<ExcelCollectPojo> collectList) throws AppMessageException {

        OutputStream ba = null;
        ba = new ByteArrayOutputStream();
        WritableWorkbook workbook = null;
        if (data == null || data.isEmpty()) {
            throw new AppMessageException("数据为空");
        }
        try {
//            File file = new File(path);
            // 创建写工作簿对象
//            WritableWorkbook workbook = Workbook.createWorkbook(file);
            workbook = Workbook.createWorkbook(ba);
            // 工作表
            WritableSheet sheet = workbook.createSheet(fileName, 0);

            //表头格式
            WritableCellFormat cellFormat = ExcelDownloadSrv.getWritableCellFormat();
            //数据行格式
            // 设置背景、字体颜色、对齐方式等等;
            WritableFont font2 = new WritableFont(WritableFont.ARIAL, 14, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
            WritableCellFormat cellFormat2 = new WritableCellFormat(font2);
            //设置文字居中对齐方式;
            cellFormat2.setAlignment(Alignment.CENTRE);
            //设置垂直居中;
            cellFormat2.setVerticalAlignment(VerticalAlignment.CENTRE);
            cellFormat2.setBackground(Colour.WHITE);
            cellFormat2.setBorder(Border.ALL, BorderLineStyle.THIN);
            cellFormat2.setWrap(true);
            //给sheet电子版中所有的列设置默认的列的宽度;
            sheet.getSettings().setDefaultColumnWidth(20);
            sheet.getSettings().setDefaultRowHeight(30 * 20);

            //单独应用样式
            if (excelStyleMap != null) {
                for (String column : excelStyleMap.keySet()) {
                    // 指定列宽
                    int styleColumnWidth = excelStyleMap.getIntValueSafely(column, ExcelStyleMap.STYLE_COLUMN_WIDTH, 0);
                    List<String> columns = new ArrayList<>(data.keySet());
                    for (int i = 0; i < columns.size(); i++) {
                        if (columns.get(i).equals(column)) {
                            sheet.setColumnView(i, styleColumnWidth);
                        }
                    }
                }
            }
//            // 设置格式(实线)
//            WritableCellFormat cellFormat = new WritableCellFormat();
//            //给sheet电子版中所有的列设置默认的列的宽度;
//            sheet.getSettings().setDefaultColumnWidth(20);
//            sheet.getSettings().setDefaultRowHeight(35 * 20);
            //行号
            int firstRow = 0;
            //填充表头
            int headerColumn = 0;
            for (String key : data.keySet()) {
                Label label = new Label(headerColumn, firstRow, key, cellFormat);
                sheet.addCell(label);
                List<String> colData = data.get(key);
                for (int i = 0; i < colData.size(); i++) {
                    Label lb = new Label(headerColumn, i + 1, Checker.getStringValue(colData.get(i)), cellFormat);
                    sheet.addCell(lb);
                }
                headerColumn++;
            }
            // 添加汇总
            if (!Checker.isNone(collectList)) {
                for (ExcelCollectPojo pojo : collectList) {
                    String[] dataArr = pojo.getDataArr();
                    for (int i = 0, j = dataArr.length; i < j; i++) {
                        Label lb = new Label(pojo.getCol() + i, pojo.getRow(), dataArr[i], cellFormat);
                        sheet.addCell(lb);
                    }
                }
            }
            //开始执行写入操作
            workbook.write();
            //关闭流
            workbook.close();
            if (ba != null) {
                try {
                    ba.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            logger.error("ExcelDownloadSrv#generateAndReturnExcelFileWithNoStyleAndCollectLocal(fileName={}, path={} ):\n {}",
                    fileName, path, e.getMessage(), e);
        }
        return ba;

    }

    /**
     * 订单统计中备注的样式(没有边框样式)
     */
    public static WritableCellFormat getCellFormat4StatRemarkWithNoSetBorder() {
        //设置字体;
        WritableFont font = new WritableFont(WritableFont.ARIAL, 14, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.DEFAULT_BACKGROUND);

        WritableCellFormat cellFormat = new WritableCellFormat(font);
        try {
            //设置背景颜色;
            cellFormat.setBackground(Colour.WHITE);
            //设置边框;
            // cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
            //设置自动换行;
//            cellFormat.setWrap(true);
            //设置文字居中对齐方式;
            cellFormat.setAlignment(Alignment.LEFT);
            //设置垂直居中;
            cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
            return cellFormat;
        } catch (WriteException e) {
            return null;
        }
    }


    /**
     * 通用的生成 Excel 文件(包含汇总)并以流返回(一点样式也没有)
     *
     * @param fileName            excel 文件名
     * @param data                需要填充的数据，key 是列名，value 是每一列的数据组成的 list, 类型必须是 {@link String}
     * @throws AppMessageException 业务层异常抛出，如传入数据为空
     * @author Walker, added on 06/27/2019.
     */
    public OutputStream generateAndReturnMealExcelFileWithNoStyleAndCollectLocal(String fileName, String path, ExcelDataMap data, ExcelStyleMap excelStyleMap,
                                                                     List<CustomExcelItem> collectList) throws AppMessageException {
        if (data == null || data.isEmpty()) {
            throw new AppMessageException("数据为空");
        }
        OutputStream ba = null;
        ba = new ByteArrayOutputStream();
        WritableWorkbook workbook = null;
        try {
//            File file = new File(path);
            // 创建写工作簿对象
             workbook = Workbook.createWorkbook(ba);
            // 工作表
            WritableSheet sheet = workbook.createSheet(fileName, 0);
            //表头格式
            WritableCellFormat cellFormat = ExcelDownloadSrv.getWritableCellFormat();
            //数据行格式
            // 设置背景、字体颜色、对齐方式等等;
            WritableFont font2 = new WritableFont(WritableFont.ARIAL, 14, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
            WritableCellFormat cellFormat2 = new WritableCellFormat(font2);
            //设置文字居中对齐方式;
            cellFormat2.setAlignment(Alignment.CENTRE);
            //设置垂直居中;
            cellFormat2.setVerticalAlignment(VerticalAlignment.CENTRE);
            cellFormat2.setBackground(Colour.WHITE);
            cellFormat2.setBorder(Border.ALL, BorderLineStyle.THIN);
            cellFormat2.setWrap(true);
            //给sheet电子版中所有的列设置默认的列的宽度;
            sheet.getSettings().setDefaultColumnWidth(20);
            sheet.getSettings().setDefaultRowHeight(30 * 20);
            //单独应用样式
            if (excelStyleMap != null) {
                for (String column : excelStyleMap.keySet()) {
                    // 指定列宽
                    int styleColumnWidth = excelStyleMap.getIntValueSafely(column, ExcelStyleMap.STYLE_COLUMN_WIDTH, 0);
                    List<String> columns = new ArrayList<>(data.keySet());
                    for (int i = 0; i < columns.size(); i++) {
                        if (columns.get(i).equals(column)) {
                            sheet.setColumnView(i, styleColumnWidth);
                        }
                    }
                }
            }

            //行号
            int firstRow = 0;
            //填充表头
            int headerColumn = 0;
            for (String key : data.keySet()) {
                Label label = new Label(headerColumn, firstRow, key, cellFormat);
                sheet.addCell(label);
                List<String> colData = data.get(key);
                for (int i = 0; i < colData.size(); i++) {
                    Label lb = new Label(headerColumn, i + 1, Checker.getStringValue(colData.get(i)), cellFormat2);
                    sheet.addCell(lb);
                }
                headerColumn++;
            }
            // 添加汇总
            if (!Checker.isNone(collectList)) {
                for (CustomExcelItem item : collectList) {
                        sheet.addCell(new Label(item.getColumn(), item.getRow(), item.getContent(),
                                item.getCellFormat() == null ? cellFormat2 : item.getCellFormat()));

                }
            }
            //开始执行写入操作
            workbook.write();
            //关闭流
            workbook.close();
            if (ba != null) {
                try {
                    ba.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            logger.error("ExcelDownloadSrv#generateAndReturnExcelFileWithNoStyleAndCollectLocal(fileName={}, path={} ):\n {}",
                    fileName, path, e.getMessage(), e);
        }
        return ba;
    }
}
