package com.tofly.feesapi.common.Excel;


import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.tofly.common.core.util.StringUtil;
import io.swagger.annotations.ApiModelProperty;
import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.*;


import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

public class AnnotationAwareClassGenerator {

    public static Class<?> createDynamicClass(List<String> requiredFields, Class<?> clazz) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(clazz));
        CtClass dynamicClass = pool.makeClass("DynamicInvoice_" + System.currentTimeMillis());

        // 复制类级别注解
        copyClassLevelAnnotations(clazz, dynamicClass);

        // 动态添加字段及注解

        for (Field field : clazz.getDeclaredFields()) {
            if (requiredFields.contains(field.getName())) {
                int index = requiredFields.indexOf(field.getName());
                addAnnotatedField(dynamicClass, field, index);
            } else {
                CtClass fieldType = pool.get(field.getType().getName());
                CtField ctField = new CtField(fieldType, field.getName(), dynamicClass);
                dynamicClass.addField(ctField);
                Annotation annotation = new Annotation(ExcelIgnore.class.getName(), dynamicClass.getClassFile().getConstPool());
                addFieldAnnotation(ctField, annotation, dynamicClass.getClassFile().getConstPool());
            }
        }
        return dynamicClass.toClass();
    }

    private static void copyClassLevelAnnotations(Class<?> sourceClass, CtClass targetClass) {
        // 处理 @Data
//        AnnotationsAttribute dataAttr = new AnnotationsAttribute(targetClass.getClassFile().getConstPool(), AnnotationsAttribute.visibleTag);
//        dataAttr.addAnnotation(new Annotation(Data.class.getName(), targetClass.getClassFile().getConstPool()));
//        targetClass.getClassFile().addAttribute(dataAttr);
        // 处理复杂的 @ContentStyle
        copyContentStyleAnnotation(sourceClass, targetClass);

        // 处理@ContentRowHeight
        ContentRowHeight rowHeight = sourceClass.getAnnotation(ContentRowHeight.class);
        if (rowHeight != null) {
            ConstPool constPool = targetClass.getClassFile().getConstPool();
            Annotation annotation = new Annotation(ContentRowHeight.class.getName(), constPool);
            annotation.addMemberValue("value", new IntegerMemberValue(constPool, rowHeight.value()));
            addClassAnnotation(targetClass, annotation);
        }
        // 处理@HeadRowHeight
        HeadRowHeight headRowHeight = sourceClass.getAnnotation(HeadRowHeight.class);
        if (headRowHeight != null) {
            ConstPool constPool = targetClass.getClassFile().getConstPool();
            Annotation annotation = new Annotation(HeadRowHeight.class.getName(), constPool);
            annotation.addMemberValue("value", new IntegerMemberValue(constPool, headRowHeight.value()));
            addClassAnnotation(targetClass, annotation);
        }
        // 处理@ColumnWidth
        ColumnWidth columnWidth = sourceClass.getAnnotation(ColumnWidth.class);
        if (columnWidth != null) {
            ConstPool constPool = targetClass.getClassFile().getConstPool();
            Annotation annotation = new Annotation(ColumnWidth.class.getName(), constPool);
            annotation.addMemberValue("value", new IntegerMemberValue(constPool, columnWidth.value()));
            addClassAnnotation(targetClass, annotation);
        }
    }

    private static void copyContentStyleAnnotation(Class<?> sourceClass, CtClass targetClass) {
        ContentStyle style = sourceClass.getAnnotation(ContentStyle.class);
        if (style != null) {
            ConstPool constPool = targetClass.getClassFile().getConstPool();
            Annotation annotation = new Annotation(ContentStyle.class.getName(), constPool);

            // 处理枚举类型的边框样式
            addEnumMember(annotation, "borderBottom", style.borderBottom(), constPool);
            addEnumMember(annotation, "borderLeft", style.borderLeft(), constPool);
            addEnumMember(annotation, "borderRight", style.borderRight(), constPool);
            addEnumMember(annotation, "borderTop", style.borderTop(), constPool);

            // 处理颜色值
            annotation.addMemberValue("bottomBorderColor", new ShortMemberValue(style.bottomBorderColor(), constPool));
            annotation.addMemberValue("topBorderColor", new ShortMemberValue(style.topBorderColor(), constPool));
            annotation.addMemberValue("leftBorderColor", new ShortMemberValue(style.leftBorderColor(), constPool));
            annotation.addMemberValue("rightBorderColor", new ShortMemberValue(style.rightBorderColor(), constPool));

            addClassAnnotation(targetClass, annotation);
        }
    }

    private static void addAnnotatedField(CtClass targetClass, Field sourceField, int index) {
//        try {
//            // 创建新字段
//            CtField ctField = new CtField(ClassPool.getDefault().get(sourceField.getType().getName()),
//                    sourceField.getName(),
//                    targetClass);
//            targetClass.addField(ctField);
//            // 复制字段注解
//            copyFieldAnnotations(sourceField, ctField, targetClass.getClassFile().getConstPool(), index);
//        } catch (Exception e) {
//            throw new RuntimeException("Failed to add field: " + sourceField.getName(), e);
//        }
        //优化JDK版本不同导致的类型兼容问题
        try {
            ClassPool classPool = new ClassPool(true);
            classPool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));

            Class<?> fieldType = sourceField.getType();
            CtClass fieldTypeCtClass;

            // 对枚举类型做特殊处理（JDK8高版本兼容）
            if (fieldType.isEnum()) {
                // 先尝试直接加载
                try {
                    fieldTypeCtClass = classPool.get(fieldType.getName());
                } catch (javassist.NotFoundException e) {
                    // 如果加载失败，手动创建枚举类型的CtClass
                    fieldTypeCtClass = classPool.makeClass(fieldType.getName());
                    fieldTypeCtClass.setModifiers(javassist.Modifier.PUBLIC | javassist.Modifier.FINAL | javassist.Modifier.ENUM);
                }
            } else {
                fieldTypeCtClass = classPool.get(fieldType.getName());
            }

            CtField ctField = new CtField(fieldTypeCtClass, sourceField.getName(), targetClass);
            targetClass.addField(ctField);
            copyFieldAnnotations(sourceField, ctField, targetClass.getClassFile().getConstPool(), index);
        } catch (Exception e) {
            throw new RuntimeException("Failed to add field: " + sourceField.getName(), e);
        }
    }

    private static void copyFieldAnnotations(Field sourceField, CtField targetField, ConstPool constPool, int index) {
        // 处理 @ExcelProperty
        ExcelProperty excelProp = sourceField.getAnnotation(ExcelProperty.class);
        //判断ExcelProperty注解是否为空，不为空直接用，为空则取ApiModelProperty注解值
        if (excelProp != null) {
            Annotation annotation = new Annotation(ExcelProperty.class.getName(), constPool);
            annotation.addMemberValue("value", createStringArray(excelProp.value(), constPool));
            annotation.addMemberValue("order", new IntegerMemberValue(constPool,index));
            if (StringUtil.isNotEmpty(excelProp.converter().getName())) {
                annotation.addMemberValue("converter", new ClassMemberValue(excelProp.converter().getName(), constPool));
            }
            addFieldAnnotation(targetField, annotation, constPool);
        } else {
            ApiModelProperty apiModelProperty = sourceField.getAnnotation(ApiModelProperty.class);
            Annotation annotation = new Annotation(ExcelProperty.class.getName(), constPool);
            if (apiModelProperty != null) {
                annotation.addMemberValue("value", createStringArray(apiModelProperty.value(), constPool));
            } else {
                annotation.addMemberValue("value", createStringArray(sourceField.getName(), constPool));
            }
            annotation.addMemberValue("order", new IntegerMemberValue(constPool,index));
            addFieldAnnotation(targetField, annotation, constPool);
        }
        // 处理 @ColumnWidth
        ColumnWidth columnWidth = sourceField.getAnnotation(ColumnWidth.class);
        if (columnWidth != null) {
            Annotation annotation = new Annotation(ColumnWidth.class.getName(), constPool);
            annotation.addMemberValue("value", new IntegerMemberValue(constPool, columnWidth.value()));
            addFieldAnnotation(targetField, annotation, constPool);
        }
    }

    // 辅助方法：添加枚举类型的注解成员
    private static void addEnumMember(Annotation annotation, String memberName, Enum<?> value, ConstPool constPool) {
        EnumMemberValue emv = new EnumMemberValue(constPool);
        emv.setType(value.getDeclaringClass().getName());
        emv.setValue(value.name());
        annotation.addMemberValue(memberName, emv);
    }

    // 辅助方法：创建字符串数组注解值
    private static ArrayMemberValue createStringArray(String[] values, ConstPool constPool) {
        ArrayMemberValue arrayMemberValue = new ArrayMemberValue(constPool);
        MemberValue[] items = Arrays.stream(values)
                .map(v -> new StringMemberValue(v, constPool))
                .toArray(MemberValue[]::new);
        arrayMemberValue.setValue(items);
        return arrayMemberValue;
    }

    // 辅助方法：创建字符串数组注解值
    private static ArrayMemberValue createStringArray(String values, ConstPool constPool) {
        ArrayMemberValue arrayMemberValue = new ArrayMemberValue(constPool);
        MemberValue[] items = new MemberValue[]{new StringMemberValue(values, constPool)};
        arrayMemberValue.setValue(items);
        return arrayMemberValue;
    }

    // 辅助方法：为类添加注解
    private static void addClassAnnotation(CtClass ctClass, Annotation annotation) {
        AnnotationsAttribute attr = new AnnotationsAttribute(ctClass.getClassFile().getConstPool(),
                AnnotationsAttribute.visibleTag);
        attr.addAnnotation(annotation);
        ctClass.getClassFile().addAttribute(attr);
    }

    // 辅助方法：为字段添加注解
    private static void addFieldAnnotation(CtField field, Annotation annotation, ConstPool constPool) {
//        AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
//        attr.addAnnotation(annotation);
//        field.getFieldInfo().addAttribute(attr);
        // 获取字段的注解属性
        AnnotationsAttribute attr = (AnnotationsAttribute) field.getFieldInfo().getAttribute(AnnotationsAttribute.visibleTag);
        if (attr == null) {
            attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
            field.getFieldInfo().addAttribute(attr);
        }
        // 添加新注解
        attr.addAnnotation(annotation);
    }
}
