package com.ruoyi.info.collection.handler;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.ruoyi.common.annotation.Required;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * EasyExcel必填字段标注处理器
 * 在Excel模板生成时，为标注了@Required注解的字段表头添加红色星号(*)标记
 *
 * @author ruoyi
 */
@Slf4j
public class RequiredFieldWriteHandler implements CellWriteHandler {

    /**
     * 实体类Class对象
     */
    private final Class<?> modelClass;

    /**
     * 必填字段列索引集合
     */
    private final Set<Integer> requiredColumns;

    /**
     * 构造函数
     *
     * @param modelClass 实体类Class对象
     */
    public RequiredFieldWriteHandler(Class<?> modelClass) {
        this.modelClass = modelClass;
        this.requiredColumns = parseRequiredFields();
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> cellDataList,
                                 Cell cell,
                                 Head head,
                                 Integer relativeRowIndex,
                                 Boolean isHead) {
        if (!Boolean.TRUE.equals(isHead) || cell == null || !requiredColumns.contains(cell.getColumnIndex())) {
            return;
        }

        Workbook workbook = cell.getSheet().getWorkbook();
        CellStyle redStyle = createRedFontStyle(workbook);

        String originalValue = cell.getStringCellValue();
        if (originalValue != null && !originalValue.endsWith("*")) {
            cell.setCellValue(originalValue + "*");
        }
        cell.setCellStyle(redStyle);
        log.info("为列[{}]的表头添加必填标记(*)", cell.getColumnIndex());
    }

    /**
     * 创建红色字体样式
     *
     * @param workbook 工作簿
     * @return 单元格样式
     */
    private CellStyle createRedFontStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体为红色
        Font font = workbook.createFont();
        font.setColor(IndexedColors.RED.getIndex());
        font.setBold(true);
        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);

        return style;
    }

    /**
     * 解析实体类中的必填字段
     *
     * @return 必填字段的列索引集合
     */
    private Set<Integer> parseRequiredFields() {
        Set<Integer> result = new HashSet<>();

        // 获取所有字段（包括父类的）
        List<Field> fields = getAllFields(modelClass);

        for (Field field : fields) {
            // 检查是否有@Required注解
            Required required = field.getAnnotation(Required.class);
            if (required == null) {
                continue;
            }

            // 获取列索引
            Integer columnIndex = getColumnIndex(field);
            if (columnIndex == null) {
                log.warn("字段[{}]没有指定@ExcelProperty的index，跳过必填标记", field.getName());
                continue;
            }

            result.add(columnIndex);
        }

        return result;
    }

    /**
     * 获取类的所有字段（包括父类的）
     *
     * @param clazz 类对象
     * @return 字段列表
     */
    private List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

    /**
     * 获取字段对应的列索引
     *
     * @param field 字段对象
     * @return 列索引
     */
    private Integer getColumnIndex(Field field) {
        ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
        if (excelProperty != null && excelProperty.index() >= 0) {
            return excelProperty.index();
        }
        return null;
    }
}
