package com.zksy.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

public class ExcelExportUtil {

    /**
     * 通用 Excel 导出方法，只导出有 @ExcelProperty 注解的字段
     * @param response HTTP 响应对象
     * @param dataList 数据列表
     * @param head 表头类型
     * @param fileName 文件名
     * @param sheetName 工作表名
     * @param <T> 数据类型
     */
    public static <T> void exportExcel(HttpServletResponse response, List<T> dataList, Class<T> head,
                                       String fileName, String sheetName) {
        try {
            // 设置响应头，明确指定xlsx格式
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("UTF-8");
            // 确保文件名有.xlsx后缀
            if (!fileName.toLowerCase().endsWith(".xlsx")) {
                fileName += ".xlsx";
            }
            // 使用ISO-8859-1编码处理文件名，防止中文乱码
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"));

            // 配置表头样式
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short)12);
            headWriteCellStyle.setWriteFont(headWriteFont);

            // 配置内容样式
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

            // 应用样式策略
            HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                    new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

            // 写入 Excel 数据，使用指定的类作为表头，会自动过滤没有 @ExcelProperty 注解的字段
            EasyExcel.write(response.getOutputStream(), head)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .sheet(sheetName)
                    .doWrite(dataList);
        } catch (IOException e) {
            // 记录异常日志
            e.printStackTrace();
            // 抛出运行时异常，由Spring MVC统一异常处理
            throw new RuntimeException("导出Excel失败", e);
        }
    }

    /**
     * 导出多 sheet 的 Excel 文件，只导出有 @ExcelProperty 注解的字段
     * @param response HTTP 响应对象
     * @param sheetDataList 多个 sheet 的数据列表
     * @param fileName 文件名
     */
    public static void exportMultiSheetExcel(HttpServletResponse response,
                                             List<SheetData<?>> sheetDataList,
                                             String fileName) {
        try {
            // 设置响应头，明确指定xlsx格式
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("UTF-8");
            // 确保文件名有.xlsx后缀
            if (!fileName.toLowerCase().endsWith(".xlsx")) {
                fileName += ".xlsx";
            }
            // 使用ISO-8859-1编码处理文件名，防止中文乱码
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"));

            // 配置表头样式
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short)12);
            headWriteCellStyle.setWriteFont(headWriteFont);

            // 配置内容样式
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

            // 应用样式策略
            HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                    new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

            // 写入多sheet Excel数据
            var excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(horizontalCellStyleStrategy).build();
            try {
                for (SheetData<?> sheetData : sheetDataList) {
                    WriteSheet writeSheet = EasyExcel.writerSheet(sheetData.getSheetName())
                            .head(sheetData.getHead()).build();
                    excelWriter.write(sheetData.getDataList(), writeSheet);
                }
            } finally {
                // 关闭 writer，释放内存
                excelWriter.finish();
            }
        } catch (IOException e) {
            e.printStackTrace();
            // 抛出运行时异常，由Spring MVC统一异常处理
            throw new RuntimeException("导出Excel失败", e);
        }
    }

    /**
     * 内部类，用于存储 sheet 数据
     */
    public static class SheetData<T> {
        private String sheetName;
        private Class<T> head;
        private List<T> dataList;

        public SheetData(String sheetName, Class<T> head, List<T> dataList) {
            this.sheetName = sheetName;
            this.head = head;
            this.dataList = dataList;
        }

        public String getSheetName() {
            return sheetName;
        }

        public Class<T> getHead() {
            return head;
        }

        public List<T> getDataList() {
            return dataList;
        }
    }
}