package com.kexue.skills.common.util;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.kexue.skills.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

// 假设 Excel 注解的定义

public class ExportUtils {

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

    /**
     * 通用Excel导出方法
     * @param list 数据集合
     * @param clazz 数据类型
     * @param outputPath 输出路径（含文件名）
     */
    public static <T> void export(List<T> list, Class<T> clazz, String outputPath) {
        if (list == null || clazz == null || StrUtil.isBlank(outputPath)) {
            log.error("导出参数异常，list、clazz、outputPath 不能为空");
            return;
        }

        // 获取带Excel注解的字段
        List<Field> fields;
        try {
            fields = Arrays.stream(ReflectUtil.getFields(clazz))
                    .filter(f -> AnnotationUtil.hasAnnotation(f, Excel.class))
                    .sorted(Comparator.comparingInt(f -> {
                        Excel excel = AnnotationUtil.getAnnotation(f, Excel.class);
                        return excel.sort();
                    }))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取带Excel注解的字段时出错", e);
            return;
        }

        // 创建ExcelWriter
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            // 设置列标题
            fields.forEach(field -> {
                Excel excelAnno = AnnotationUtil.getAnnotation(field, Excel.class);
                String title = getColumnTitle(field, excelAnno);
                writer.addHeaderAlias(field.getName(), title);
            });

            // 写入数据
            writer.write(list, true);

            // 输出文件
            try {
                writer.flush(FileUtil.file(outputPath));
                log.info("Excel文件导出成功，路径：{}", outputPath);
            } catch (Exception e) {
                log.error("导出Excel文件到路径 {} 时出错", outputPath, e);
            }
        } catch (Exception e) {
            log.error("创建ExcelWriter或写入数据时出错", e);
        }
    }

    /**
     * 获取列标题
     */
    public static String getColumnTitle(Field field, Excel excelAnno) {
        // 优先使用Excel注解的label
        if (StrUtil.isNotBlank(excelAnno.label())) {
            return excelAnno.label();
        }

        // 次选ApiModelProperty的value
        ApiModelProperty apiModelProperty = AnnotationUtil.getAnnotation(field, ApiModelProperty.class);
        if (apiModelProperty != null && StrUtil.isNotBlank(apiModelProperty.value())) {
            return apiModelProperty.value();
        }

        // 最后使用字段名
        return field.getName();
    }

    // 新增流式导出方法
    public static <T> void export(List<T> list, Class<T> clazz, OutputStream outputStream) {
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            writer.setOnlyAlias(true);

            // ============== 新增样式配置 ==============
            // 获取样式工具
            StyleSet styleSet = writer.getStyleSet();

            // 表头样式配置
            CellStyle headerStyle = styleSet.getHeadCellStyle();

            // 创建表头字体
            Font headerFont = writer.createFont();
            headerFont.setFontName("微软雅黑");      // 字体
            headerFont.setBold(true);              // 加粗
            headerFont.setFontHeightInPoints((short)12); // 字号
            headerFont.setColor(IndexedColors.WHITE.getIndex()); // 字体颜色

            // 应用字体到表头样式
            headerStyle.setFont(headerFont);

            // 设置表头背景色
            headerStyle.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            // 设置水平居中
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            // ============== 样式配置结束 ==============

            List<Field> fields = getSortedFields(clazz);
            for (Field field : fields) {
                Excel excelAnno = AnnotationUtil.getAnnotation(field, Excel.class);
                String title = getColumnTitle(field, excelAnno);
                System.out.println(title);
                writer.addHeaderAlias(field.getName(), title);
            }

            fields.forEach(field -> {
                if (!isSupportedType(field.getType())) {
                    log.warn("字段 {} 类型 {} 不支持导出，将被忽略", field.getName(), field.getType().getSimpleName());
                    System.out.println("字段 " + field.getName() + " 类型 " + field.getType().getSimpleName() + " 不支持导出，将被忽略");
                }
            });

            List<Map<String, Object>> dataList = new ArrayList<>();
            for (T t : list) {
                Map<String, Object> stringObjectMap = BeanUtil.beanToMap(t);
                stringObjectMap.forEach((key, value) -> {
                    if (value == null) {
                        stringObjectMap.put(key, "");
                        return;
                    }

                    if (value instanceof Date) {
                        stringObjectMap.put(key, DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss"));
                    } else if (value instanceof Number) { // 包含Integer/Long等
                        stringObjectMap.put(key, value);
                    } else if (value instanceof Boolean) {
                        Boolean boolValue = (Boolean) value; // 显式类型转换
                        stringObjectMap.put(key, boolValue ? "是" : "否"); // 布尔值本地化
                    } else if (value.getClass().isPrimitive()) {
                        stringObjectMap.put(key, String.valueOf(value));
                    } else if (!(value instanceof String)) {
                        // 复杂类型处理（按需选择）
                        stringObjectMap.put(key, "");
                    }
                });
                dataList.add(stringObjectMap);
            }

            writer.write(dataList, true);
            writer.flush(outputStream);
        }
    }

    // 类型检查方法
    private static boolean isSupportedType(Class<?> type) {
        return type.isPrimitive()
                || Number.class.isAssignableFrom(type)
                || Date.class.isAssignableFrom(type)
                || String.class == type
                || Boolean.class == type;
    }

    // 提取公共字段处理逻辑
    public static <T> List<Field> getSortedFields(Class<T> clazz) {
        return Arrays.stream(ReflectUtil.getFields(clazz))
                .filter(f -> AnnotationUtil.hasAnnotation(f, Excel.class))
                .sorted(Comparator.comparingInt(f ->
                        AnnotationUtil.getAnnotation(f, Excel.class).sort()))
                .collect(Collectors.toList());
    }

    // 扩展Web导出方法
    public static <T> void webExport(List<T> list, Class<T> clazz, String fileName,
                                     HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
        response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
        export(list, clazz, response.getOutputStream()); // 调用新的流式导出方法
    }

}