package com.sckw.excel.config.easyexcel;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.excel.annotation.EasyExcel;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author lfdc
 * @description 状态枚举信息获取（code->value，1代表失败 进行转换）
 * @date 2023-07-28 10:07:51
 */
@Slf4j
public class ExcelConverter implements Converter<String> {
    @Override
    public Class supportJavaTypeKey() {
        //指定状态码类型
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        //指定需要获取的参数类型
        return CellDataTypeEnum.STRING;
    }

    /**
     * 导出时转换
     *
     * @param value               状态码
     * @param contentProperty     字段属性
     * @param globalConfiguration 全局配置
     * @return
     * @throws Exception
     */
    @Override
    public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        //获取字段属性中的注解
        Field field = contentProperty.getField();
        EasyExcel easyExcel = field.getAnnotation(EasyExcel.class);
        //获取注解中的枚举信息
        Class<? extends Enum> type = easyExcel.type();
        //获取枚举类的方法名 “codeOf”就是自己编写的函数，Integer.class 指定入参类型
        int status = easyExcel.status();
        boolean flag = easyExcel.flag();
        Object invoke = null;
        if (flag) {
            invoke = verifyTranslate(value, status, type);
        } else {
            //将转换的值进行返回
            return new WriteCellData(value.toString());
        }
        //将转换的值进行返回
        if (invoke == null) {
            return new WriteCellData();
        }
        return new WriteCellData(invoke.toString());
    }

    /**
     * 应对不同枚举处理
     *
     * @param value
     * @param status
     * @param type
     * @return
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private Object verifyTranslate(String value, int status, Class<? extends Enum> type) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object invoke = null;
        try {
            if (NumberConstant.ONE == status) {
                //获取枚举类的方法名 【getDestination】就是自己编写的函数，String.class 指定入参类型
                Method codeOf = type.getMethod("getDestination", String.class);
                //反射执行方法，此方法得到的是一个枚举实例（具体得到什么，结合自身项目）
                invoke = codeOf.invoke(type, value);
            } else if (NumberConstant.TWO == status) {
                //获取枚举类的方法名 【getName】就是自己编写的函数，String.class 指定入参类型
                Method codeOf = type.getMethod("getName", Integer.class);
                //反射执行方法，此方法得到的是一个枚举实例（具体得到什么，结合自身项目）
                invoke = codeOf.invoke(type, Integer.valueOf(value));
            } else {
                //获取枚举类的方法名 “codeOf”就是自己编写的函数，Integer.class 指定入参类型
                Method codeOf = type.getMethod("getEntityByCode", Integer.class);
                //反射执行方法，此方法得到的是一个枚举实例（具体得到什么，结合自身项目）
                invoke = codeOf.invoke(type, value);
                //枚举实例调用getname方法，得到name的值
                Method getName = invoke.getClass().getMethod("getDestination");
                //将转换的值进行返回
                invoke = String.valueOf(getName.invoke(invoke));
            }
        } catch (NoSuchMethodException e) {
            log.info("NoSuchMethodException ERROR:{}", e.getMessage(), e);
            throw new RuntimeException(e);
        } catch (SecurityException e) {
            log.info("SecurityException ERROR:{}", e.getMessage(), e);
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            log.info("IllegalAccessException ERROR:{}", e.getMessage(), e);
            throw new RuntimeException(e);
        } catch (IllegalArgumentException e) {
            log.info("IllegalArgumentException ERROR:{}", e.getMessage(), e);
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            log.info("InvocationTargetException ERROR:{}", e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return invoke;
    }

}
