package com.changhu.common.utils;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Set;
import java.util.stream.Stream;

/**
 * @author 20252
 * @createTime 2024/8/5 下午4:11
 * @desc JavaClassToTsUtils...
 */
public class JavaClassToTsUtil {

    public static <T> String parse(Class<T> tClass) {
        //类名字
        StringBuilder tsInterface = new StringBuilder("interface " + tClass.getSimpleName() + " {");
        //获取class所有属性
        Field[] fields = tClass.getDeclaredFields();

        for (Field field : fields) {
            tsInterface
                    .append("\n\t")
                    .append("/** ")
                    .append(field.getAnnotation(Schema.class) != null ? field.getAnnotation(Schema.class).description() : field.getName())
                    .append(" **/")
                    .append("\n\t")
                    .append(field.getName())
                    .append(isMust(field) ? "" : "?")
                    .append(":")
                    .append(convertJavaTypeToTS(field.getType()))
                    .append(";");
        }
        return tsInterface
                .append("\n")
                .append("}")
                .toString();
    }

    /**
     * 将Java类型转化未ts类型
     *
     * @param type Java类型
     * @return ts类型
     */
    private static String convertJavaTypeToTS(Class<?> type) {
        Set<Class<?>> stringList = Set.of(
                String.class,
                LocalDateTime.class,
                LocalDate.class,
                LocalTime.class
        );
        Set<Class<?>> boolList = Set.of(
                Boolean.class,
                boolean.class
        );
        Set<Class<?>> numberList = Set.of(
                Integer.class, int.class,
                Double.class, double.class,
                Float.class, float.class,
                Long.class, long.class,
                Short.class, short.class,
                BigDecimal.class,
                Byte.class, byte.class
        );
        if (stringList.contains(type)) {
            return "string";
        } else if (boolList.contains(type)) {
            return "boolean";
        } else if (numberList.contains(type)) {
            return "number";
        } else {
            return "unsupported";
        }
    }

    /**
     * 检查字段是否必须
     *
     * @param field 字段
     * @return 是否必须
     */
    private static boolean isMust(Field field) {
        return Stream.of(
                NotNull.class,
                NotEmpty.class,
                NotBlank.class
        ).anyMatch(field::isAnnotationPresent);
    }

}
