package com.pm.common.utils.poi;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ExcelUtilPageData {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 导出excel 但是office打开文件会出现 Excel无法打开文件"xx.xlsx"，因为文件格式或文件扩展名无效。请确定文件未损坏，并且文件扩展名与文件的格式匹配。
     *  所以导出的文件需要时 xls
     * @param response
     * @param exportCondition
     * @param manName
     * @param sheetTitle
     * @param title
     * @param list
     */
    public static void exportXLS(HttpServletResponse response, String exportCondition, String manName, String sheetTitle, String[] title, List list) {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet(sheetTitle);

        // 表头样式（加粗，水平居中，垂直居中）
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中

        HSSFFont fontStyle = wb.createFont();
        fontStyle.setBold(true); // 替换setBoldweight
        fontStyle.setFontName("宋体");
        cellStyle.setFont(fontStyle);

        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12);

        // 标题样式（加粗，垂直居中）
        HSSFCellStyle cellStyle2 = wb.createCellStyle();
        cellStyle2.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle2.setAlignment(HorizontalAlignment.CENTER);
        cellStyle2.setFont(fontStyle);

        // 设置边框样式
        cellStyle2.setBorderBottom(BorderStyle.THIN);
        cellStyle2.setBorderLeft(BorderStyle.THIN);
        cellStyle2.setBorderTop(BorderStyle.THIN);
        cellStyle2.setBorderRight(BorderStyle.THIN);

        // 字段样式（垂直居中）
        HSSFCellStyle cellStyle3 = wb.createCellStyle();
        cellStyle3.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置边框样式
        cellStyle3.setBorderBottom(BorderStyle.THIN);
        cellStyle3.setBorderLeft(BorderStyle.THIN);
        cellStyle3.setBorderTop(BorderStyle.THIN);
        cellStyle3.setBorderRight(BorderStyle.THIN);

        // 创建标题
        HSSFRow rowTitle = sheet.createRow(0);
        rowTitle.setHeightInPoints(20);

        HSSFCell hc;
        for (int i = 0; i < title.length; i++) {
            hc = rowTitle.createCell(i);
            String titleStr = title[i];
            int commaIndex = titleStr.lastIndexOf(",");
            String displayValue = commaIndex >= 0 ? titleStr.substring(0, commaIndex) : titleStr;
            hc.setCellValue(displayValue);
            hc.setCellStyle(cellStyle2);
        }

        try {
            int i = 1;
            for (Object obj : list) {
                HSSFRow rowBody = sheet.createRow(i);
                rowBody.setHeightInPoints(20);

                for (int j = 0; j < title.length; j++) {
                    String titleStr = title[j];
                    String fieldName = titleStr.substring(titleStr.lastIndexOf(",") + 1);

                    Object va = null;
                    if (obj instanceof Map) {
                        va = ((Map) obj).get(fieldName);
                    } else {
                        Field f = obj.getClass().getDeclaredField(fieldName);
                        if (f != null) {
                            f.setAccessible(true);
                            va = f.get(obj);
                        }
                    }
                    if (null == va) va = "";
                    if (va instanceof Date) va = sdf.format(va);

                    hc = rowBody.createCell(j);
                    hc.setCellValue(va.toString());
                    hc.setCellStyle(cellStyle3);
                }
                i++;
            }

            // 自动调整列宽
            for (int k = 0; k < title.length; k++) {
                sheet.autoSizeColumn(k);
            }

            // 设置打印区域
            wb.setPrintArea(0, 0, title.length - 1, 0, i - 1);

            // 设置输出
            String fileName = (sheetTitle == null ? "导出" : sheetTitle) +
                    new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".xlsx";

            response.reset();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO-8859-1"));

            ServletOutputStream out = response.getOutputStream();
            wb.write(out);
            out.flush();
            out.close();
        } catch (Exception ex) {
            Logger.getLogger(ExcelUtilPageData.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void exportXLSX(HttpServletResponse response, String exportCondition,
                              String manName, String sheetTitle, String[] title, List list) {
        // 创建XSSFWorkbook代替HSSFWorkbook
        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet(sheetTitle);

        // 创建样式
        XSSFCellStyle headerStyle = wb.createCellStyle();
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        XSSFFont headerFont = wb.createFont();
        headerFont.setBold(true);
        headerFont.setFontName("宋体");
        headerStyle.setFont(headerFont);

        // 标题样式
        XSSFCellStyle titleStyle = wb.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        titleStyle.setFont(headerFont);

        // 设置边框
        titleStyle.setBorderBottom(BorderStyle.THIN);
        titleStyle.setBorderLeft(BorderStyle.THIN);
        titleStyle.setBorderTop(BorderStyle.THIN);
        titleStyle.setBorderRight(BorderStyle.THIN);

        // 内容样式
        XSSFCellStyle contentStyle = wb.createCellStyle();
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentStyle.setBorderBottom(BorderStyle.THIN);
        contentStyle.setBorderLeft(BorderStyle.THIN);
        contentStyle.setBorderTop(BorderStyle.THIN);
        contentStyle.setBorderRight(BorderStyle.THIN);
        // 内容字体颜色为黑色
        XSSFFont blackFont = wb.createFont();
        blackFont.setColor(new XSSFColor(java.awt.Color.BLACK, new DefaultIndexedColorMap()));
        blackFont.setFontName("Arial");
        blackFont.setFontHeightInPoints((short) 10); // 10号字体
        contentStyle.setFont(blackFont);

        // 创建标题行
        XSSFRow titleRow = sheet.createRow(0);
        titleRow.setHeightInPoints(20);

        // 设置标题行背景色为灰色
        XSSFCellStyle grayStyle = wb.createCellStyle();
        grayStyle.cloneStyleFrom(titleStyle); // 继承原有样式
        grayStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(128, 128, 128), new DefaultIndexedColorMap()));
        grayStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        grayStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        grayStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中

        // 内容样式也设置为居中
        contentStyle.setAlignment(HorizontalAlignment.CENTER);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 创建白色加粗字体 (标题行字体)
        XSSFFont whiteBoldFont = wb.createFont();
        whiteBoldFont.setColor(new XSSFColor(java.awt.Color.WHITE, new DefaultIndexedColorMap()));
        whiteBoldFont.setBold(true);
        whiteBoldFont.setFontName("Arial");
        whiteBoldFont.setFontHeightInPoints((short) 10); // 10号字体.setFontHeightInPoints((short) 10); // 10号字体
        grayStyle.setFont(whiteBoldFont);

        for (int i = 0; i < title.length; i++) {
            XSSFCell cell = titleRow.createCell(i);
            String titleStr = title[i];
            cell.setCellValue(titleStr.substring(0, titleStr.lastIndexOf(",")));
            cell.setCellStyle(grayStyle);// 设置标题行样式 深灰色
        }

        try {
            // 填充数据
            int rowNum = 1;
            for (Object obj : list) {
                XSSFRow row = sheet.createRow(rowNum);
                row.setHeightInPoints(20);

                for (int colNum = 0; colNum < title.length; colNum++) {
                    String titleStr = title[colNum];
                    String fieldName = titleStr.substring(titleStr.lastIndexOf(",") + 1);

                    Object value = getFieldValue(obj, fieldName);
                    if (value == null) value = "";
                    if (value instanceof Date) value = sdf.format(value);

                    XSSFCell cell = row.createCell(colNum);
                    cell.setCellValue(value.toString());
                    cell.setCellStyle(contentStyle);
                }
                rowNum++;
            }
            // 其他列自动调整
            // 优化列宽计算
            for (int i = 0; i < title.length; i++) {
                sheet.autoSizeColumn(i);
                // 设置最小列宽
                sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 5000));
            }

            // 设置输出
            String fileName = (sheetTitle == null ? "导出" : sheetTitle) +
                    new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date()) + ".xlsx";

            response.reset();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO-8859-1"));

            ServletOutputStream out = response.getOutputStream();
            wb.write(out);
            out.flush();
            out.close();
        } catch (Exception ex) {
            Logger.getLogger(ExcelUtilPageData.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private static Object getFieldValue(Object obj, String fieldName) throws Exception {
        if (obj instanceof Map) {
            return ((Map) obj).get(fieldName);
        } else {
            Field f = obj.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            return f.get(obj);
        }
    }
}
