package com.clx.performance.utils.excel;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @Author: aiqingguo
 * @Description:
 * @Date: 2022/8/18 14:33
 * @Version: 1.0
 */
public class ExcelUtil {

    @Getter
    @AllArgsConstructor
    public enum CellStyleType {
        CONTENT_CENTER(1),          //内容居中
        CONTENT_LEFT(2),            //内容居左
        CONTENT_RIGHT(3),           //内容居右

        TIME_LEFT(11),               //时间左边
        TIME_RIGHT(12),              //时间右边

        ;

        private final Integer code;

    }

    /**
     * 导出
     */
    public static void export(ExcelSheet excelSheet) {

        // 创建excel
        SXSSFWorkbook workbook = create(excelSheet);

        // 导出
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
        try {
            workbook.write(response.getOutputStream());
        }catch (Exception e){
            throw new RuntimeException("文件导出失败");
        }
    }

    /**
     * 创建excel
     */
    public static SXSSFWorkbook create(ExcelSheet excelSheet) {
        List<ExcelField> fieldList = excelSheet.getFieldList();
        List<ExcelField> fieldSecondList = excelSheet.getFieldSecondList();
        List<List<ExcelData>> dataList = excelSheet.getDataList();

        SXSSFWorkbook workbook = new SXSSFWorkbook();

        //创建sheet
        SXSSFSheet sheet = workbook.createSheet(excelSheet.getName());


        int dataFieldSize = 0;
        for (int i = 0; i < fieldList.size(); i++) {
            dataFieldSize += fieldList.get(i).getSpan();
        }

        // 设置列宽
        for (int i = 0, columnIdx = 0; i < fieldList.size(); i++) {

            Integer width = null;
            if (fieldList.get(i).getWidth() != null){width = fieldList.get(i).getWidth()/fieldList.get(i).getSpan();}

            for (int j = 0; j < fieldList.get(i).getSpan(); j++) {
                if (width != null) {sheet.setColumnWidth(columnIdx, width);}
                columnIdx++;
            }
        }
        if (fieldSecondList != null) {
            for (int i = 0, columnIdx = 0; i < fieldSecondList.size(); i++) {

                Integer width = null;
                if (fieldSecondList.get(i).getWidth() != null){width = fieldSecondList.get(i).getWidth()/fieldSecondList.get(i).getSpan();}

                for (int j = 0; j < fieldSecondList.get(i).getSpan(); j++) {
                    if (width != null) {sheet.setColumnWidth(columnIdx, width);}
                    columnIdx++;
                }
            }
        }

        //添加标题
        int row = 0;
        CellRangeAddress cellRangeAddress = new CellRangeAddress(row, row, 0, dataFieldSize - 1);
        SXSSFRow rowTitle = sheet.createRow(row++);
        sheet.addMergedRegion(cellRangeAddress);
        rowTitle.setHeightInPoints(30);

        SXSSFCell titleCell = rowTitle.createCell(0);
        titleCell.setCellValue(excelSheet.getTitle());
        titleCell.setCellStyle(getTitleStyle(workbook));

        //时间
        if (StringUtils.isNotBlank(excelSheet.getTime())) {
            CellRangeAddress timeCellRangeAddress = new CellRangeAddress(row, row, 0, dataFieldSize - 1);
            SXSSFRow rowTime = sheet.createRow(row++);
            sheet.addMergedRegion(timeCellRangeAddress);

            SXSSFCell timeCell = rowTime.createCell(0);
            timeCell.setCellValue(excelSheet.getTime());
            Integer styleType = excelSheet.getTimeStyleType();
            if (null != styleType) {
                timeCell.setCellStyle(getCellStyle(workbook, styleType));
            }
        }

        //添加表头
        CellStyle headCellStyle = getHeadStyle(workbook);
        SXSSFRow rowHead = sheet.createRow(row++);
        for (int i = 0, columnIdx=0; i < fieldList.size(); i++) {
            SXSSFCell headCell = rowHead.createCell(columnIdx);
            if (fieldList.get(i).getFieldName() != null) {
                headCell.setCellValue(fieldList.get(i).getFieldName());
            }

            if (fieldList.get(i).getSpan()>1) {
                CellRangeAddress cellAddresses = new CellRangeAddress(row-1, row-1, columnIdx, columnIdx + fieldList.get(i).getSpan()-1);
                sheet.addMergedRegion(cellAddresses);
            }

            Integer styleType = fieldList.get(i).getStyleType();
            if (null != styleType) {
                headCell.setCellStyle(getCellStyle(workbook, styleType));
            } else {
                headCell.setCellStyle(headCellStyle);
            }
            columnIdx += fieldList.get(i).getSpan();
        }

        //添加二级表头
        if (fieldSecondList != null) {
            CellStyle headCellStyleSecond = getHeadStyle(workbook);
            SXSSFRow rowHeadSecond = sheet.createRow(row++);
            for (int i = 0, columnIdx = 0; i < fieldSecondList.size(); i++) {
                SXSSFCell headCell = rowHeadSecond.createCell(columnIdx);
                if (fieldSecondList.get(i).getFieldName()!=null) {
                    headCell.setCellValue(fieldSecondList.get(i).getFieldName());
                }

                if (fieldSecondList.get(i).getSpan() > 1){
                    CellRangeAddress cellAddresses = new CellRangeAddress(row-1, row-1, columnIdx, columnIdx + fieldSecondList.get(i).getSpan()-1);
                    sheet.addMergedRegion(cellAddresses);
                }

                Integer styleType = fieldSecondList.get(i).getStyleType();
                if (null != styleType) {
                    headCell.setCellStyle(getCellStyle(workbook, styleType));
                } else {
                    headCell.setCellStyle(headCellStyleSecond);
                }
                columnIdx += fieldSecondList.get(i).getSpan();
            }
        }

        //内容
        SXSSFRow rowData;
        int dataSize = dataList.size();
        for (int i = 0; i < dataSize; i++) {
            rowData = sheet.createRow(row++);
            for (int j = 0; j < dataFieldSize; j++) {
                SXSSFCell dataCell = rowData.createCell(j);
                ExcelData excelData = dataList.get(i).get(j);
                setCellValue(dataCell, excelData);

                Integer styleType = dataList.get(i).get(j).getStyleType();
                if (null != styleType) {
                    dataCell.setCellStyle(getCellStyle(workbook, styleType));
                }

            }
        }

        return workbook;
    }

    /**
     * 设置值
     */
    private static void setCellValue(SXSSFCell dataCell, ExcelData excelData) {
        if (ExcelData.DataType.STRING.getValue().equals(excelData.getDataType())) {
            String stringValue = excelData.getStringValue();
            dataCell.setCellValue(stringValue);
        } else if (ExcelData.DataType.NUMERIC.getValue().equals(excelData.getDataType())) {
            if (null == excelData.getStyleType()) {
                excelData.setStyleType(CellStyleType.CONTENT_RIGHT.getCode());
            }
            dataCell.setCellValue(excelData.getDoubleValue());
        }
    }

    /**
     * 设置标题字体
     */
    private static Font getTitleFont(SXSSFWorkbook workbook) {
        Font ztFont = workbook.createFont();
        ztFont.setColor(Font.COLOR_NORMAL);
        ztFont.setFontHeightInPoints((short) 22);
        return ztFont;
    }

    /**
     * 设置标题样式
     */
    private static CellStyle getTitleStyle(SXSSFWorkbook workbook) {
        Font font = getTitleFont(workbook);

        CellStyle style = workbook.createCellStyle();
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }

    /**
     * 设置格式
     */
    private static Font getHeadFont(SXSSFWorkbook workbook) {
        Font ztFont = workbook.createFont();
        ztFont.setBold(true);
        return ztFont;
    }

    /**
     * 设置表头样式
     */
    private static CellStyle getHeadStyle(SXSSFWorkbook workbook) {
        Font headFont = getHeadFont(workbook);

        CellStyle style = workbook.createCellStyle();
        style.setFont(headFont);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setAlignment(HorizontalAlignment.CENTER);

        return style;
    }


    //获取单元格样式
    private static CellStyle getCellStyle(SXSSFWorkbook workbook, Integer cellStyleType) {

        if (CellStyleType.CONTENT_CENTER.getCode().equals(cellStyleType)) {
            return contentCenterStyle(workbook);
        }
        if (CellStyleType.CONTENT_LEFT.getCode().equals(cellStyleType)) {
            return contentLeftStyle(workbook);
        }
        if (CellStyleType.CONTENT_RIGHT.getCode().equals(cellStyleType)) {
            return contentRightStyle(workbook);
        }

        if (CellStyleType.TIME_LEFT.getCode().equals(cellStyleType)) {
            return timeLeftStyle(workbook);
        }
        if (CellStyleType.TIME_RIGHT.getCode().equals(cellStyleType)) {
            return timeRightStyle(workbook);
        }

        return workbook.createCellStyle();
    }

    /**
     * 内容居中
     */
    private static CellStyle contentCenterStyle(SXSSFWorkbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        return cellStyle;
    }

    /**
     * 内容居右
     */
    private static CellStyle contentLeftStyle(SXSSFWorkbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.LEFT);

        return cellStyle;
    }

    /**
     * 内容居右
     */
    private static CellStyle contentRightStyle(SXSSFWorkbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.RIGHT);

        return cellStyle;
    }

    /**
     * 时间样式
     */
    private static CellStyle timeLeftStyle(SXSSFWorkbook workbook) {

        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontName("宋体");
        cellStyle.setFont(font);

        return cellStyle;
    }

    private static CellStyle timeRightStyle(SXSSFWorkbook workbook) {

        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontName("宋体");
        cellStyle.setFont(font);

        return cellStyle;
    }

}
