package com.ruoyi.cms.util.excel;

import com.ruoyi.common.annotation.Excel;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.List;

/**
 * 就业统计Excel导出工具（支持动态传递列数）
 */
public class StaticsExcelUtil<T> {
    private final Class<T> clazz;

    public StaticsExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    public void exportEmploymentExcel(HttpServletResponse response,
                                      String timeRange,
                                      String[] statLabels,
                                      Integer[] statValues,
                                      List<T> dataList,
                                      String sheetName,
                                      int maxColumnNum) throws Exception {
        // 参数校验
        if (statLabels == null || statValues == null || statLabels.length != statValues.length) {
            throw new IllegalArgumentException("统计标签数组和数值数组长度必须一致！");
        }
        if (maxColumnNum < 1) {
            throw new IllegalArgumentException("最大列数不能小于1！");
        }
        int maxColumnIndex = maxColumnNum - 1; // 列索引从0开始，比如9列对应索引0-8

        // 1. 创建工作簿和工作表
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(sheetName);

        // 2. 第1行：统计时间（动态合并列）
        Row row1 = sheet.createRow(0);
        Cell cell1 = row1.createCell(0);
        cell1.setCellValue("统计时间：" + timeRange);
        // 合并第1行的0 ~ maxColumnIndex列（动态列数）
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, maxColumnIndex));
        setCellStyle(cell1, true, workbook);

        // 3. 第2行：统计指标（适配动态列数）
        Row row2 = sheet.createRow(1);
        int cellIndex = 0;
        for (int i = 0; i < statLabels.length; i++) {
            if (cellIndex > maxColumnIndex) {
                break; // 超出动态列数则停止
            }
            // 指标名称单元格
            Cell labelCell = row2.createCell(cellIndex);
            labelCell.setCellValue(statLabels[i]);
            setCellStyle(labelCell, true, workbook);

            // 指标数值单元格（判断剩余列是否足够）
            int valueCellIndex = cellIndex + 1;
            if (valueCellIndex > maxColumnIndex) {
                // 剩余列不足，合并单元格存放“名称+数值”
                sheet.addMergedRegion(new CellRangeAddress(1, 1, cellIndex, maxColumnIndex));
                labelCell.setCellValue(statLabels[i] + "：" + statValues[i]);
                break;
            } else {
                // 正常填充数值
                Cell valueCell = row2.createCell(valueCellIndex);
                valueCell.setCellValue(statValues[i]);
                setCellStyle(valueCell, false, workbook);
                cellIndex = valueCellIndex + 1;
            }
        }

        // 4. 第3行：明细数据表头（反射获取@Excel注解）
        Row headerRow = sheet.createRow(2);
        Field[] fields = clazz.getDeclaredFields();
        int headerCellIndex = 0;
        for (Field field : fields) {
            Excel excel = field.getAnnotation(Excel.class);
            if (excel != null && headerCellIndex < maxColumnNum) { // 不超过动态列数
                Cell headerCell = headerRow.createCell(headerCellIndex++);
                headerCell.setCellValue(excel.name());
                setCellStyle(headerCell, true, workbook);
            }
        }

        // 5. 第4行开始：填充明细数据
        int dataRowNum = 3;
        for (T data : dataList) {
            Row dataRow = sheet.createRow(dataRowNum++);
            int dataCellIndex = 0;
            for (Field field : fields) {
                Excel excel = field.getAnnotation(Excel.class);
                if (excel != null && dataCellIndex < maxColumnNum) { // 不超过动态列数
                    field.setAccessible(true);
                    Cell dataCell = dataRow.createCell(dataCellIndex++);
                    Object value = field.get(data);
                    if (value instanceof String) {
                        dataCell.setCellValue((String) value);
                    } else if (value instanceof Integer) {
                        dataCell.setCellValue((Integer) value);
                    }
                    setCellStyle(dataCell, false, workbook);
                }
            }
        }

        // 6. 自动调整列宽（动态列数）
        autoSizeColumns(sheet, maxColumnNum);

        // 7. 写入响应流
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(sheetName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=UTF-8''" + fileName + ".xlsx");
        try (OutputStream os = response.getOutputStream()) {
            workbook.write(os);
            os.flush();
        }
        workbook.close();
    }

    /**
     * 自定义单元格样式
     */
    private void setCellStyle(Cell cell, boolean isHeader, Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 11);

        if (isHeader) {
            font.setBold(true);
            style.setFillForegroundColor((short) 22); // 浅灰色索引
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        }

        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        cell.setCellStyle(style);
    }

    /**
     * 自动调整列宽（动态列数）
     */
    private void autoSizeColumns(Sheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 2000);
        }
    }
}