package com.jwipc.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.jwipc.dto.ExportDataDTO;
import com.jwipc.dto.ExportEnumDataDTO;
import java.io.IOException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2024/2/28 22:17
 * @desc
 */
public class EasyExcelUtilsAyn {

    public static void trendsModelWriteStock(String fileName, String sheetName, List data,
                                           List<ExportDataDTO> exportDataDTOS) throws IOException
    {
        trendsModelWriteToStock(fileName, sheetName, data, exportDataDTOS, false);
    }

    public static void trendsModelWriteToStock(String fileName, String sheetName, List data,
                                          List<ExportDataDTO> exportDataDTOS, boolean tripleHeader) throws IOException
    {
//        fileName = "D:\\" + fileName + ".xlsx";
        EasyExcel.write(fileName).registerConverter(new LongStringConverter())
                .head(head(exportDataDTOS)).automaticMergeHead(false)
                .registerWriteHandler(new CustomCellWriteHandlerTwo(exportDataDTOS, tripleHeader))
                .sheet(sheetName).doWrite(
                        dataList(data,
                                exportDataDTOS.stream().map(ExportDataDTO::getField).collect(Collectors.toList()),
                                exportDataDTOS));
    }



    /**
     * 设置Excel头
     *
     * @param exportDataDTOS 导出数据信息
     * @return
     */
    public static List<List<String>> head(List<ExportDataDTO> exportDataDTOS) {
        List<List<String>> list = new ArrayList<>();
        for (ExportDataDTO value : exportDataDTOS) {
            List<String> head = new ArrayList<>();
            if (StrUtil.isNotEmpty(value.getHeader())) {
                head.add(value.getHeader());
            }
            head.add(value.getTitle());
            head.add(value.getField());
            list.add(head);
        }
        return list;
    }

    /**
     * 设置表格信息
     *
     * @param dataList 查询出的数据
     * @param fileList 需要显示的字段
     * @return
     */
    public static List<List<Object>> dataList(List<Object> dataList, List<String> fileList,
                                              List<ExportDataDTO> exportDataDTOS)
    {
        List<List<Object>> list = new ArrayList<>();
        for (Object person : dataList) {
            List<Object> data = new ArrayList<>();
            for (String fieldName : fileList) {
                boolean su = false;
                for (ExportDataDTO exportDataDTO : exportDataDTOS) {
                    //枚举、字典、主数据格式化
                    if (fieldName.equals(exportDataDTO.getField()) &&
                            CollectionUtil.isNotEmpty(exportDataDTO.getExportEnum())) {
                        if (ObjectUtil.isNotEmpty(getFieldValue(fieldName, person))) {
                            ExportEnumDataDTO exportEnumDataDTO = exportDataDTO.getExportEnum().stream()
                                    .filter(s -> s.getCode().equals(String.valueOf(getFieldValue(fieldName, person))))
                                    .toList().stream().findFirst().orElse(null);
                            if (ObjectUtil.isNotNull(exportEnumDataDTO)) {
                                data.add(exportEnumDataDTO.getCodeWithDesc());
                                su = true;
                                break;
                            }
                        } else {
                            ExportEnumDataDTO exportEnumDataDTO = exportDataDTO.getExportEnum().stream()
                                    .filter(s -> StrUtil.isEmpty(s.getCode()) &&
                                            StrUtil.isNotEmpty(s.getCodeWithDesc()))
                                    .toList().stream().findFirst().orElse(null);
                            if (ObjectUtil.isNotNull(exportEnumDataDTO)) {
                                data.add(exportEnumDataDTO.getCodeWithDesc());
                                su = true;
                                break;
                            }
                        }
                    }
                    //日期格式化
                    if (fieldName.equals(exportDataDTO.getField()) &&
                            StrUtil.isNotEmpty(exportDataDTO.getExportDateFormatter())) {
                        if (ObjectUtil.isNotEmpty(getFieldValue(fieldName, person))) {
                            try {
                                LocalDateTime localDateTime = LocalDateTimeUtil.parse(
                                        String.valueOf(getFieldValue(fieldName, person)));
                                data.add(LocalDateTimeUtil.format(localDateTime, "dateTime".equals(
                                        exportDataDTO.getExportDateFormatter()) ? DatePattern.NORM_DATETIME_PATTERN :
                                        DatePattern.NORM_DATE_PATTERN));
                                su = true;
                                break;
                            } catch (Exception e) {
                                DateTime dateTime = DateUtil.parse(
                                        String.valueOf(getFieldValue(fieldName, person)));
                                data.add(DateUtil.format(dateTime, "dateTime".equals(
                                        exportDataDTO.getExportDateFormatter()) ? DatePattern.NORM_DATETIME_PATTERN :
                                        DatePattern.NORM_DATE_PATTERN));
                                su = true;
                                break;
                            }
                        }
                    }
                }
                if (!su) {
                    //通过反射根据需要显示的字段，获取对应的属性值
                    //是map直接处理
                    if (person instanceof Map) {
                        data.add(MapUtil.getStr((Map) person, fieldName));
                    } else {
                        data.add(getFieldValue(fieldName, person));
                    }
                }
            }
            list.add(data);
        }
        return list;
    }

    /**
     * 根据传入的字段获取对应的get方法，如name,对应的getName方法
     *
     * @param fieldName 字段名
     * @param person    对象
     * @return
     */
    public static Object getFieldValue(String fieldName, Object person) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = person.getClass().getMethod(getter);
            return method.invoke(person);
        } catch (Exception e) {
            return null;
        }
    }

}
