package com.ylx.massage.utils;

import cn.hutool.core.collection.CollUtil;
import com.ylx.massage.domain.SensitiveWord;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Excel生成工具类
 * <p>
 * 提供生成Excel文件的功能，支持敏感词数据的导出。
 * 使用Apache POI库创建.xls格式的Excel文件。
 * </p>
 *
 * @author ylx
 * @version 1.0
 * @since 2024
 */
public class ExcelExportUtils {

    private static final Logger log = LoggerFactory.getLogger(ExcelExportUtils.class);

    /**
     * 列宽定义
     */
    private static final int COLUMN_WIDTH_WORD = 30;      // 敏感词列宽
    private static final int COLUMN_WIDTH_CATEGORY = 20;  // 分类列宽
    private static final int COLUMN_WIDTH_LEVEL = 10;     // 等级列宽
    private static final int COLUMN_WIDTH_STATUS = 10;    // 状态列宽
    private static final int COLUMN_WIDTH_REMARK = 40;    // 备注列宽

    /**
     * 导出敏感词数据到Excel文件
     * <p>
     * 将敏感词列表写入Excel工作簿，并输出到HTTP响应流。
     * Excel文件格式：
     * - 第一行：表头（敏感词、分类、等级、状态、备注）
     * - 第二行起：数据行
     * </p>
     *
     * @param wordList 敏感词数据列表
     * @param response HTTP响应对象
     * @throws IOException 当写入响应流失败时抛出
     */
    public static void exportSensitiveWords(List<SensitiveWord> wordList, HttpServletResponse response) throws IOException {
        if (CollUtil.isEmpty(wordList)) {
            log.warn("敏感词数据为空，导出空文件");
        }

        Workbook workbook = null;
        OutputStream outputStream = null;

        try {
            // 1. 创建工作簿（.xls格式）
            workbook = new HSSFWorkbook();

            // 2. 创建工作表
            Sheet sheet = workbook.createSheet("敏感词库");

            // 3. 创建表头样式
            CellStyle headerStyle = createHeaderStyle(workbook);

            // 4. 创建数据样式
            CellStyle dataStyle = createDataStyle(workbook);

            // 5. 创建表头行
            Row headerRow = sheet.createRow(0);
            createHeaderRow(headerRow, headerStyle);

            // 6. 设置列宽
            setColumnWidths(sheet);

            // 7. 填充数据
            if (CollUtil.isNotEmpty(wordList)) {
                int rowNum = 1;
                for (SensitiveWord word : wordList) {
                    Row dataRow = sheet.createRow(rowNum++);
                    fillDataRow(dataRow, word, dataStyle);
                }
                log.info("成功写入 {} 条敏感词数据到Excel", wordList.size());
            }

            // 8. 生成文件名
            String fileName = generateFileName();

            // 9. 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

            // 10. 写入响应流
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();

            log.info("敏感词Excel文件导出成功，文件名：{}", fileName);
        } catch (Exception e) {
            log.error("导出敏感词Excel文件失败", e);
            throw new IOException("导出Excel文件失败：" + e.getMessage());
        } finally {
            // 关闭资源
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("关闭Workbook失败", e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("关闭OutputStream失败", e);
                }
            }
        }
    }

    /**
     * 创建表头样式
     * <p>
     * 表头样式：字体加粗、居中对齐、背景色为浅灰色。
     * </p>
     *
     * @param workbook 工作簿对象
     * @return 表头样式对象
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);

        // 设置对齐方式
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置背景色
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

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

        return style;
    }

    /**
     * 创建数据样式
     * <p>
     * 数据样式：左对齐、带边框。
     * </p>
     *
     * @param workbook 工作簿对象
     * @return 数据样式对象
     */
    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 11);
        style.setFont(font);

        // 设置对齐方式
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

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

        // 设置自动换行
        style.setWrapText(true);

        return style;
    }

    /**
     * 创建表头行
     * <p>
     * 在指定行中创建表头单元格。
     * </p>
     *
     * @param row 行对象
     * @param style 单元格样式
     */
    private static void createHeaderRow(Row row, CellStyle style) {
        String[] headers = {"敏感词", "分类"};

        for (int i = 0; i < headers.length; i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(style);
        }
    }

    /**
     * 设置列宽
     * <p>
     * 为工作表的每一列设置合适的宽度。
     * </p>
     *
     * @param sheet 工作表对象
     */
    private static void setColumnWidths(Sheet sheet) {
        sheet.setColumnWidth(0, COLUMN_WIDTH_WORD * 256);      // 敏感词
        sheet.setColumnWidth(1, COLUMN_WIDTH_CATEGORY * 256);  // 分类
        sheet.setColumnWidth(2, COLUMN_WIDTH_LEVEL * 256);     // 等级
        sheet.setColumnWidth(3, COLUMN_WIDTH_STATUS * 256);    // 状态
        sheet.setColumnWidth(4, COLUMN_WIDTH_REMARK * 256);    // 备注
    }

    /**
     * 填充数据行
     * <p>
     * 将敏感词对象的数据写入行中。
     * </p>
     *
     * @param row 行对象
     * @param word 敏感词对象
     * @param style 单元格样式
     */
    private static void fillDataRow(Row row, SensitiveWord word, CellStyle style) {
        // 1. 敏感词
        Cell wordCell = row.createCell(0);
        wordCell.setCellValue(word.getWord() != null ? word.getWord() : "");
        wordCell.setCellStyle(style);

        // 2. 分类
        Cell categoryCell = row.createCell(1);
        categoryCell.setCellValue(word.getCategory() != null ? word.getCategory() : "");
        categoryCell.setCellStyle(style);

        // 3. 等级
        /*Cell levelCell = row.createCell(2);
        levelCell.setCellValue(word.getLevel() != null ? word.getLevel() : 1);
        levelCell.setCellStyle(style);*/

        // 4. 状态
        /*Cell statusCell = row.createCell(3);
        statusCell.setCellValue(word.getStatus() != null ? word.getStatus() : 1);
        statusCell.setCellStyle(style);*/

        // 5. 备注
        /*Cell remarkCell = row.createCell(4);
        remarkCell.setCellValue(word.getRemark() != null ? word.getRemark() : "");
        remarkCell.setCellStyle(style);*/
    }

    /**
     * 生成导出文件名
     * <p>
     * 生成格式为：全量敏感词库_当前日期时间.xls
     * 日期时间格式：yyyyMMddHHmmss
     * </p>
     *
     * @return 文件名字符串
     */
    private static String generateFileName() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateTime = sdf.format(new Date());
        return "全量敏感词库_" + dateTime + ".xls";
    }
}
