package fcb.project.manager.base.utils;

import lombok.extern.log4j.Log4j2;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
public class ExcelUtil {

    private static final String EXCEL_XLS = "xls";
    private static final String EXCEL_XLSX = "xlsx";
    private List<String> coleNames;

    public ExcelUtil(List<String> coleNames) {
        if (CollectionUtils.isEmpty(coleNames)) {
            throw new RuntimeException("导出列名称集合为空");
        }
        this.coleNames = coleNames;
    }

    public Workbook writeExcel(List<Map> dataList, int columnCount, String xlsxPath, String titleStr) {
        OutputStream out = null;
        try {
            // 获取总列数
            int columnNumCount = columnCount;
            // 读取Excel文档
            File xlsxFile = new File(xlsxPath);
            HSSFWorkbook workBook = new HSSFWorkbook();

            // sheet 对应一个工作页
            HSSFSheet sheet = workBook.createSheet();
            HSSFCellStyle cellstyle = workBook.createCellStyle();

            //标题，合并单元格，字体加粗
            /*
             * 这个对象中有四个参数
             * 第一个代表：起始行
             * 第二个代表：结束行
             * 第三个代表：起始列
             * 第四个代表：结束列
             */
            CellRangeAddress cra = new CellRangeAddress(0, 0, 0, coleNames.size() -1);
            //把合并样式添加到sheet中
            sheet.addMergedRegion(cra);

            //居中
            cellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER_SELECTION);

            //加粗
            HSSFFont font = workBook.createFont();
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            cellstyle.setFont(font);

            HSSFRow title = sheet.createRow((short) 0);
            //设置行高
            title.setHeight((short) 500);
            HSSFCell titleCell = title.createCell((short) 0);
            titleCell.setCellValue(titleStr);

            cellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
            cellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
            cellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
            cellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

            titleCell.setCellStyle(cellstyle);

            //设置边框
            HSSFCellStyle setBorder = workBook.createCellStyle();
            setBorder.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
            setBorder.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
            setBorder.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
            setBorder.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

            HSSFRow hssfRow = sheet.createRow((short) 1);
            sheet.createFreezePane(0, 1);
            for (int i = 0; i < coleNames.size(); ++i) {
                HSSFCell cell = hssfRow.createCell((short)i);
                cell.setCellValue(coleNames.get(i));
                cell.setCellStyle(setBorder);
            }
            // 创建文件输出流，输出电子表格：这个必须有，否则你在sheet上做的任何操作都不会有效
            out = new FileOutputStream(xlsxPath);
            workBook.write(out);
            /**
             * 往Excel中写新数据
             */
            for (int j = 0; j < dataList.size(); j++) {
                // 创建一行：从第二行开始，跳过属性列
                Row row = sheet.createRow(j + 2);
                // 得到要插入的每一条记录
                Map<String, String> dataMap = dataList.get(j);

                for (int i = 0; i < coleNames.size(); ++i) {
                    String value = dataMap.get(coleNames.get(i));
                    Cell cell = row.createCell(i);
                    cell.setCellValue(value);

                    cell.setCellStyle(setBorder);
                    if(value != null){
                        setSizeColumn(sheet, coleNames.size());
                    }
                }
            }
            // 创建文件输出流，准备输出电子表格：这个必须有，否则你在sheet上做的任何操作都不会有效
            out = new FileOutputStream(xlsxPath);
            workBook.write(out);
            log.info("数据导出成功");
            return workBook;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *  自适应列宽
     * @param sheet
     * @param columnLength 列数
     */
    private void setSizeColumn(Sheet sheet, int columnLength) {
        for (int columnNum = 0; columnNum <= columnLength; columnNum++) {
            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                Row currentRow; // 当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow =  sheet.createRow(rowNum);
                } else {
                    currentRow =  sheet.getRow(rowNum);
                }
                if (currentRow.getCell(columnNum) != null) {
                    Cell currentCell = currentRow.getCell(columnNum);
                    if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                        int length = currentCell.getStringCellValue().getBytes().length;
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            if(columnNum == 0){
                continue;
            }
            sheet.setColumnWidth(columnNum, columnWidth * 256);
        }
    }

    public List<String> getColeNames() {
        return coleNames;
    }

    public static void main(String[] args) {
        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("BankName", "BankName");
        dataMap.put("Addr", "Addr");
        dataMap.put("Phone", "Phone");
        List<Map> list = new ArrayList<Map>();
        list.add(dataMap);
//        ExcelUtil.writeExcel(list, 3, "D:/writeExcel.xls","");
    }

}
