package cn.gov.customs.wxjy.common.utils.poi;

import cn.gov.customs.wxjy.common.annotation.Excel;
import cn.gov.customs.wxjy.common.core.text.Convert;
import cn.gov.customs.wxjy.common.exception.UtilException;
import cn.gov.customs.wxjy.common.utils.DateUtils;
import cn.gov.customs.wxjy.common.utils.DictUtils;
import cn.gov.customs.wxjy.common.utils.StringUtils;
import cn.gov.customs.wxjy.common.utils.reflect.ReflectUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 动态列Excel导出工具类（优化版）
 * 支持动态列导出、注解配置、样式处理、数据转换、字典转换等功能
 *
 * @param <T> 数据模型类型
 */
public class DynamicExcelUtil<T> {
    private static final Logger log = LoggerFactory.getLogger(DynamicExcelUtil.class);

    // 公式特殊字符，用于防止CSV注入
    private static final String[] FORMULA_STR = { "=", "-", "+", "@" };
    private static final String FORMULA_REGEX_STR = "=|-|\\+|@";

    private Class<T> clazz;
    private List<T> dataList;
    private Set<String> exportFields;
    private Map<String, Excel> excelAnnotationMap;
    private Map<String, CellStyle> styles;
    private Workbook workbook;
    private Sheet sheet;
    private List<Object[]> sortedFieldList; // 排序后的字段列表 [Field, Excel注解]
    private String title;
    private String sheetName;
    private boolean includeTitle = false;
    private int currentRowNum = 0;
    private Map<Integer, Double> statistics = new HashMap<>();

    // 字典缓存，避免重复查询
    private Map<String, String> dictCache = new HashMap<>();

    /**
     * 构造器
     *
     * @param clazz 数据模型类
     */
    public DynamicExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
        this.exportFields = new LinkedHashSet<>(); // 保持顺序
        this.excelAnnotationMap = new HashMap<>();
        this.sortedFieldList = new ArrayList<>();
        initExcelAnnotations();
    }

    /**
     * 初始化Excel注解映射
     */
    private void initExcelAnnotations() {
        // 获取所有字段（包括父类）
        List<Field> allFields = new ArrayList<>();
        Class<?> currentClass = clazz;
        while (currentClass != null && currentClass != Object.class) {
            allFields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
            currentClass = currentClass.getSuperclass();
        }

        // 收集Excel注解
        for (Field field : allFields) {
            if (field.isAnnotationPresent(Excel.class)) {
                Excel excel = field.getAnnotation(Excel.class);
                excelAnnotationMap.put(field.getName(), excel);
            }
        }
    }

    /**
     * 设置需要导出的字段（字符串数组）
     *
     * @param fieldNames 字段名数组
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setExportFields(String... fieldNames) {
        if (fieldNames != null) {
            exportFields.addAll(Arrays.asList(fieldNames));
        }
        return this;
    }

    /**
     * 设置需要导出的字段（集合）
     *
     * @param fieldNames 字段名集合
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setExportFields(Collection<String> fieldNames) {
        if (fieldNames != null) {
            exportFields.addAll(fieldNames);
        }
        return this;
    }

    /**
     * 设置需要导出的字段（逗号分隔的字符串）
     *
     * @param fieldNamesStr 逗号分隔的字段名字符串
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setExportFieldsByString(String fieldNamesStr) {
        if (StringUtils.isNotEmpty(fieldNamesStr)) {
            String[] fieldArray = fieldNamesStr.split(",");
            for (String field : fieldArray) {
                String trimmedField = field.trim();
                if (StringUtils.isNotEmpty(trimmedField)) {
                    exportFields.add(trimmedField);
                }
            }
        }
        return this;
    }

    /**
     * 设置数据列表
     *
     * @param dataList 数据列表
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setData(List<T> dataList) {
        this.dataList = dataList;
        return this;
    }

    /**
     * 设置标题
     *
     * @param title 标题
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setTitle(String title) {
        this.title = title;
        this.includeTitle = StringUtils.isNotEmpty(title);
        return this;
    }

    /**
     * 设置工作表名称
     *
     * @param sheetName 工作表名称
     * @return 当前实例
     */
    public DynamicExcelUtil<T> setSheetName(String sheetName) {
        this.sheetName = sheetName;
        return this;
    }

    /**
     * 获取所有可导出的字段名称（按注解sort排序）
     *
     * @return 字段名称列表
     */
    public List<String> getAllExportableFields() {
        List<String> fields = new ArrayList<>(excelAnnotationMap.keySet());
        // 按注解的sort属性排序
        fields.sort(Comparator.comparingInt(fieldName -> {
            Excel excel = excelAnnotationMap.get(fieldName);
            return excel != null ? excel.sort() : 0;
        }));
        return fields;
    }

    /**
     * 准备导出数据
     */
    private void prepareExport() {
        // 如果没有指定导出字段，导出所有有注解的字段（按sort排序）
        if (exportFields.isEmpty()) {
            // 获取所有字段并按sort排序
            List<Map.Entry<String, Excel>> sortedEntries = excelAnnotationMap.entrySet()
                    .stream()
                    .sorted(Comparator.comparingInt(entry -> entry.getValue().sort()))
                    .collect(Collectors.toList());

            for (Map.Entry<String, Excel> entry : sortedEntries) {
                exportFields.add(entry.getKey());
            }
        }

        // 过滤掉不存在的字段
        exportFields.removeIf(fieldName -> !excelAnnotationMap.containsKey(fieldName));

        // 获取字段对象和注解
        sortedFieldList.clear();
        for (String fieldName : exportFields) {
            try {
                Field field = getField(clazz, fieldName);
                if (field != null) {
                    Excel excel = excelAnnotationMap.get(fieldName);
                    sortedFieldList.add(new Object[]{field, excel});
                }
            } catch (NoSuchFieldException e) {
                log.warn("字段 {} 在类 {} 中不存在", fieldName, clazz.getName());
            }
        }

        // 如果没有指定顺序，按注解的sort排序
        if (sortedFieldList.size() > 1) {
            sortedFieldList.sort(Comparator.comparingInt(o -> ((Excel) o[1]).sort()));
        }
    }

    /**
     * 递归获取字段（包括父类）
     */
    private Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && superClass != Object.class) {
                return getField(superClass, fieldName);
            }
            throw e;
        }
    }

    /**
     * 创建工作簿和样式
     */
    private void createWorkbookAndStyles() {
        // 创建SXSSFWorkbook，支持大数据量
        this.workbook = new SXSSFWorkbook(500);
        this.sheet = workbook.createSheet(StringUtils.isNotEmpty(sheetName) ? sheetName : "Sheet1");

        // 创建样式
        createStyles();
    }

    /**
     * 创建样式
     */
    private void createStyles() {
        this.styles = new HashMap<>();

        // 标题样式
        CellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = workbook.createFont();
        titleFont.setFontName("宋体");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        titleStyle.setFont(titleFont);
        styles.put("title", titleStyle);

        // 表头样式 - 默认样式
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headerStyle.setBorderTop(BorderStyle.THIN);
        headerStyle.setBorderBottom(BorderStyle.THIN);
        headerStyle.setBorderLeft(BorderStyle.THIN);
        headerStyle.setBorderRight(BorderStyle.THIN);
        headerStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        headerStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        headerStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        headerStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font headerFont = workbook.createFont();
        headerFont.setFontName("宋体");
        headerFont.setFontHeightInPoints((short) 11);
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        styles.put("header", headerStyle);

        // 数据样式 - 默认样式
        CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(HorizontalAlignment.LEFT);
        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        dataStyle.setBorderTop(BorderStyle.THIN);
        dataStyle.setBorderBottom(BorderStyle.THIN);
        dataStyle.setBorderLeft(BorderStyle.THIN);
        dataStyle.setBorderRight(BorderStyle.THIN);
        dataStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        dataStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        dataStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        dataStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        Font dataFont = workbook.createFont();
        dataFont.setFontName("宋体");
        dataFont.setFontHeightInPoints((short) 10);
        dataStyle.setFont(dataFont);
        styles.put("data", dataStyle);

        // 创建数字样式
        createNumberStyles();

        // 创建日期样式
        createDateStyles();

        // 创建文本样式（防止科学计数法）
        CellStyle textStyle = workbook.createCellStyle();
        textStyle.cloneStyleFrom(dataStyle);
        DataFormat textFormat = workbook.createDataFormat();
        textStyle.setDataFormat(textFormat.getFormat("@"));
        styles.put("text", textStyle);
    }

    /**
     * 创建数字样式
     */
    private void createNumberStyles() {
        // 普通数字样式
        CellStyle numberStyle = workbook.createCellStyle();
        numberStyle.cloneStyleFrom(styles.get("data"));
        numberStyle.setAlignment(HorizontalAlignment.RIGHT);
        DataFormat numberFormat = workbook.createDataFormat();
        numberStyle.setDataFormat(numberFormat.getFormat("#,##0"));
        styles.put("number", numberStyle);

        // 两位小数样式
        CellStyle decimalStyle = workbook.createCellStyle();
        decimalStyle.cloneStyleFrom(styles.get("data"));
        decimalStyle.setAlignment(HorizontalAlignment.RIGHT);
        DataFormat decimalFormat = workbook.createDataFormat();
        decimalStyle.setDataFormat(decimalFormat.getFormat("#,##0.00"));
        styles.put("decimal", decimalStyle);
    }

    /**
     * 创建日期样式
     */
    private void createDateStyles() {
        // 日期样式
        CellStyle dateStyle = workbook.createCellStyle();
        dateStyle.cloneStyleFrom(styles.get("data"));
        dateStyle.setAlignment(HorizontalAlignment.CENTER);
        DataFormat dateFormat = workbook.createDataFormat();
        dateStyle.setDataFormat(dateFormat.getFormat("yyyy-mm-dd"));
        styles.put("date", dateStyle);

        // 日期时间样式
        CellStyle datetimeStyle = workbook.createCellStyle();
        datetimeStyle.cloneStyleFrom(styles.get("data"));
        datetimeStyle.setAlignment(HorizontalAlignment.CENTER);
        DataFormat datetimeFormat = workbook.createDataFormat();
        datetimeStyle.setDataFormat(datetimeFormat.getFormat("yyyy-mm-dd hh:mm:ss"));
        styles.put("datetime", datetimeStyle);
    }

    /**
     * 创建标题行
     */
    private void createTitleRow() {
        if (includeTitle && StringUtils.isNotEmpty(title)) {
            Row titleRow = sheet.createRow(currentRowNum++);
            titleRow.setHeightInPoints(30);

            // 创建标题单元格
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellValue(title);
            titleCell.setCellStyle(styles.get("title"));

            // 合并单元格
            int lastCol = Math.max(0, sortedFieldList.size() - 1);
            if (lastCol > 0) {
                sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, lastCol));
            }
        }
    }

    /**
     * 创建表头行
     */
    private void createHeaderRow() {
        Row headerRow = sheet.createRow(currentRowNum++);
        headerRow.setHeightInPoints(25);

        int colIndex = 0;
        for (Object[] fieldInfo : sortedFieldList) {
            Excel excel = (Excel) fieldInfo[1];
            Cell cell = headerRow.createCell(colIndex);
            cell.setCellValue(excel.name());
            cell.setCellStyle(styles.get("header"));

            // 设置列宽，width()返回double，需要转换为int
            setColumnWidth(colIndex, excel);

            colIndex++;
        }
    }

    /**
     * 设置列宽
     */
    private void setColumnWidth(int colIndex, Excel excel) {
        double widthValue = excel.width();
        int width;

        if (widthValue > 0) {
            // width()返回double，转换为int，公式为(width + 0.72) * 256
            width = (int) ((widthValue + 0.72) * 256);
        } else {
            // 根据列名长度自动设置宽度
            int nameLength = excel.name().getBytes().length;
            width = Math.max(nameLength * 256 + 512, 2000);
        }

        // 设置最大最小限制
        width = Math.min(width, 255 * 256); // 最大255个字符
        width = Math.max(width, 1500); // 最小约6个字符

        sheet.setColumnWidth(colIndex, width);
    }

    /**
     * 填充数据行
     */
    private void fillDataRows() {
        if (dataList == null || dataList.isEmpty()) {
            return;
        }

        for (T item : dataList) {
            Row dataRow = sheet.createRow(currentRowNum++);
            dataRow.setHeightInPoints(20);

            int colIndex = 0;
            for (Object[] fieldInfo : sortedFieldList) {
                Field field = (Field) fieldInfo[0];
                Excel excel = (Excel) fieldInfo[1];

                Cell cell = dataRow.createCell(colIndex);

                try {
                    field.setAccessible(true);
                    Object value = field.get(item);

                    // 应用单元格样式
                    applyCellStyle(cell, excel);

                    // 设置单元格值
                    setCellValue(cell, value, excel);

                    // 统计
                    addStatistics(colIndex, value, excel);

                } catch (Exception e) {
                    log.error("设置单元格值失败，字段：{}", field.getName(), e);
                    cell.setCellValue("");
                    cell.setCellStyle(styles.get("data"));
                }

                colIndex++;
            }
        }
    }

    /**
     * 应用单元格样式
     */
    private void applyCellStyle(Cell cell, Excel excel) {
        CellStyle style = getCellStyle(excel);
        cell.setCellStyle(style);
    }

    /**
     * 根据注解获取单元格样式
     */
    private CellStyle getCellStyle(Excel excel) {
        String styleKey;

        // 根据单元格类型确定样式
        switch (excel.cellType()) {
            case NUMERIC:
                // 根据scale判断小数位数
                if (excel.scale() > 0) {
                    styleKey = "decimal";
                } else {
                    styleKey = "number";
                }
                break;
            case TEXT:
                styleKey = "text";
                break;
            // 在若依框架的Excel.ColumnType中，没有DATE和DATETIME枚举值
            // 日期格式化是通过dateFormat属性实现的
            default:
                styleKey = "data";
        }

        CellStyle baseStyle = styles.get(styleKey);

        // 克隆样式以避免修改全局样式
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.cloneStyleFrom(baseStyle);

        // 设置水平对齐方式
        switch (excel.align()) {
            case LEFT:
                cellStyle.setAlignment(HorizontalAlignment.LEFT);
                break;
            case CENTER:
                cellStyle.setAlignment(HorizontalAlignment.CENTER);
                break;
            case RIGHT:
                cellStyle.setAlignment(HorizontalAlignment.RIGHT);
                break;
        }

        return cellStyle;
    }

    /**
     * 设置单元格值
     */
    private void setCellValue(Cell cell, Object value, Excel excel) {
        if (value == null) {
            cell.setCellValue(excel.defaultValue());
            return;
        }

        // 首先转换单元格值
        String cellValue = convertCellValue(value, excel);

        // 防止CSV注入
        if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) {
            cellValue = "\t" + cellValue;
        }

        // 根据单元格类型设置值
        switch (excel.cellType()) {
            case NUMERIC:
                try {
                    if (value instanceof Number) {
                        double numValue = ((Number) value).doubleValue();
                        // 如果有scale设置，进行格式化
                        if (excel.scale() >= 0) {
                            BigDecimal bd = BigDecimal.valueOf(numValue);
                            bd = bd.setScale(excel.scale(), excel.roundingMode());
                            cell.setCellValue(bd.doubleValue());
                        } else {
                            cell.setCellValue(numValue);
                        }
                    } else {
                        cell.setCellValue(Double.parseDouble(cellValue));
                    }
                } catch (NumberFormatException e) {
                    cell.setCellValue(cellValue);
                }
                break;
            default:
                // 对于日期类型，如果设置了dateFormat，这里cellValue已经是格式化后的字符串
                cell.setCellValue(StringUtils.isNull(cellValue) ? excel.defaultValue() : cellValue);
                break;
        }
    }

    /**
     * 转换单元格值
     */
    private String convertCellValue(Object value, Excel excel) {
        if (value == null) {
            return excel.defaultValue();
        }

        String strValue = value.toString();

        // 日期格式化 - 如果有dateFormat属性，优先使用
        if (StringUtils.isNotEmpty(excel.dateFormat())) {
            return parseDateToStr(excel.dateFormat(), value);
        }

        // 字典转换
        if (StringUtils.isNotEmpty(excel.dictType())) {
            String cacheKey = excel.dictType() + "_" + strValue;
            if (!dictCache.containsKey(cacheKey)) {
                String dictLabel = DictUtils.getDictLabel(excel.dictType(), strValue, excel.separator());
                dictCache.put(cacheKey, dictLabel != null ? dictLabel : strValue);
            }
            return dictCache.get(cacheKey);
        }

        // 读取转换器（例如：0=男,1=女）
        if (StringUtils.isNotEmpty(excel.readConverterExp())) {
            return convertByExp(strValue, excel.readConverterExp(), excel.separator());
        }

        return strValue;
    }

    /**
     * 添加统计信息
     */
    private void addStatistics(int columnIndex, Object value, Excel excel) {
        if (excel.isStatistics() && value != null) {
            try {
                double numValue = 0;
                if (value instanceof Number) {
                    numValue = ((Number) value).doubleValue();
                } else {
                    numValue = Double.parseDouble(value.toString());
                }
                statistics.merge(columnIndex, numValue, Double::sum);
            } catch (NumberFormatException e) {
                // 忽略非数字值
            }
        }
    }

    /**
     * 创建统计行
     */
    private void createStatisticsRow() {
        if (!statistics.isEmpty()) {
            Row statRow = sheet.createRow(currentRowNum++);
            Cell totalCell = statRow.createCell(0);
            totalCell.setCellValue("合计");
            totalCell.setCellStyle(styles.get("header"));

            for (Map.Entry<Integer, Double> entry : statistics.entrySet()) {
                Cell cell = statRow.createCell(entry.getKey());
                cell.setCellValue(entry.getValue());

                // 应用数字样式
                CellStyle numberStyle = workbook.createCellStyle();
                numberStyle.cloneStyleFrom(styles.get("decimal"));
                cell.setCellStyle(numberStyle);
            }
        }
    }

    /**
     * 日期格式化
     */
    private String parseDateToStr(String dateFormat, Object value) {
        if (value == null) {
            return "";
        }
        if (value instanceof Date) {
            return DateUtils.parseDateToStr(dateFormat, (Date) value);
        }
        return value.toString();
    }

    /**
     * 解析导出值 0=男,1=女,2=未知
     */
    private String convertByExp(String propertyValue, String converterExp, String separator) {
        if (StringUtils.isEmpty(propertyValue) || StringUtils.isEmpty(converterExp)) {
            return propertyValue;
        }

        StringBuilder result = new StringBuilder();
        String[] convertSource = converterExp.split(",");

        // 处理多个值的情况（用分隔符分隔）
        String[] propertyValues = propertyValue.split(separator);

        for (String propVal : propertyValues) {
            boolean found = false;
            for (String item : convertSource) {
                String[] itemArray = item.split("=");
                if (itemArray.length == 2 && propVal.trim().equals(itemArray[0].trim())) {
                    if (result.length() > 0) {
                        result.append(separator);
                    }
                    result.append(itemArray[1].trim());
                    found = true;
                    break;
                }
            }
            // 如果没有找到匹配，使用原值
            if (!found) {
                if (result.length() > 0) {
                    result.append(separator);
                }
                result.append(propVal.trim());
            }
        }

        return result.toString();
    }

    /**
     * 导出Excel到HttpServletResponse
     *
     * @param response HttpServletResponse
     * @param fileName 文件名（不需要后缀）
     * @throws IOException 异常
     */
    public void exportToResponse(HttpServletResponse response, String fileName) throws IOException {
        // 准备数据
        prepareExport();

        // 创建工作簿和样式
        createWorkbookAndStyles();

        // 创建标题行
        createTitleRow();

        // 创建表头行
        createHeaderRow();

        // 填充数据
        fillDataRows();

        // 创建统计行
        createStatisticsRow();

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");

        // 对文件名进行URL编码
        String encodedFileName = URLEncoder.encode(
                        fileName + ".xlsx", StandardCharsets.UTF_8.toString())
                .replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);

        // 写入响应流
        workbook.write(response.getOutputStream());

        // 清理临时文件（SXSSFWorkbook会生成临时文件）
        if (workbook instanceof SXSSFWorkbook) {
            ((SXSSFWorkbook) workbook).dispose();
        }
        workbook.close();
    }

    /**
     * 导出Excel（简化方法）
     *
     * @param response HttpServletResponse
     * @param dataList 数据列表
     * @param sheetName 工作表名
     * @throws IOException 异常
     */
    public void exportExcel(HttpServletResponse response, List<T> dataList, String sheetName) throws IOException {
        setData(dataList)
                .setSheetName(sheetName)
                .exportToResponse(response, sheetName);
    }

    /**
     * 导出Excel（完整方法）
     *
     * @param response HttpServletResponse
     * @param dataList 数据列表
     * @param sheetName 工作表名
     * @param title 标题
     * @param exportFields 导出的字段（逗号分隔的字符串）
     * @throws IOException 异常
     */
    public void exportExcel(HttpServletResponse response, List<T> dataList,
                            String sheetName, String title, String exportFields) throws IOException {
        setData(dataList)
                .setSheetName(sheetName)
                .setTitle(title)
                .setExportFieldsByString(exportFields)
                .exportToResponse(response, sheetName);
    }

    /**
     * 导出Excel（完整方法，数组参数）
     *
     * @param response HttpServletResponse
     * @param dataList 数据列表
     * @param sheetName 工作表名
     * @param title 标题
     * @param exportFields 导出的字段数组
     * @throws IOException 异常
     */
    public void exportExcel(HttpServletResponse response, List<T> dataList,
                            String sheetName, String title, String... exportFields) throws IOException {
        setData(dataList)
                .setSheetName(sheetName)
                .setTitle(title)
                .setExportFields(exportFields)
                .exportToResponse(response, sheetName);
    }

    /**
     * 导出到文件
     *
     * @param filePath 文件路径
     * @throws IOException 异常
     */
    public void exportToFile(String filePath) throws IOException {
        prepareExport();
        createWorkbookAndStyles();
        createTitleRow();
        createHeaderRow();
        fillDataRows();
        createStatisticsRow();

        try (OutputStream fos = new java.io.FileOutputStream(filePath)) {
            workbook.write(fos);
        }

        if (workbook instanceof SXSSFWorkbook) {
            ((SXSSFWorkbook) workbook).dispose();
        }
        workbook.close();
    }

    /**
     * 导出到字节数组
     *
     * @return 字节数组
     * @throws IOException 异常
     */
    public byte[] exportToBytes() throws IOException {
        prepareExport();
        createWorkbookAndStyles();
        createTitleRow();
        createHeaderRow();
        fillDataRows();
        createStatisticsRow();

        try (java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream()) {
            workbook.write(baos);
            return baos.toByteArray();
        } finally {
            if (workbook instanceof SXSSFWorkbook) {
                ((SXSSFWorkbook) workbook).dispose();
            }
            workbook.close();
        }
    }

    /**
     * 清空缓存和状态
     */
    public void clear() {
        this.exportFields.clear();
        this.dictCache.clear();
        this.statistics.clear();
        this.sortedFieldList.clear();
        this.title = null;
        this.sheetName = null;
        this.includeTitle = false;
        this.currentRowNum = 0;
    }

    /**
     * 获取导出字段列表（用于调试）
     *
     * @return 导出字段列表
     */
    public List<String> getExportFieldList() {
        return new ArrayList<>(exportFields);
    }
}