package com.bc.exam.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.bc.exam.core.annon.Dict;
import com.bc.exam.core.api.ApiRest;
import com.bc.exam.core.utils.Reflections;
import com.bc.exam.modules.system.service.SysDictService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @Description 描述:数据字典AOP类，处理数据字典值
 * @Author A贾宇婷034244310
 * @Date 20260615
 */
@Aspect
//@Component
@Slf4j
public class DictAspect {


    @Autowired
    private SysDictService sysDictService;

    /**
     * 切入Controller执行
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("execution(public *  com.bc.exam..*.*Controller.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        return this.translate(pjp);
    }

    /**
     * 进行翻译并返回，调用前必须实现：BaseDictService
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    public Object translate(ProceedingJoinPoint pjp) throws Throwable {
        // 处理字典
        return this.parseAllDictText(pjp.proceed());
    }

    /**
     * 转换全部数据字典
     *
     * @param result
     */
    private Object parseAllDictText(Object result) {

        // 非ApiRest类型不处理
        if (result instanceof ApiRest) {
            parseFullDictText(result);
        }

        return result;
    }


    /**
     * 转换所有类型的数据字典、包含子列表
     *
     * @param result
     */
    private void parseFullDictText(Object result) {

        try {

            Object rest = ((ApiRest) result).getData();

            // 不处理普通数据类型
            if (rest == null || this.isBaseType(rest.getClass())) {
                return;
            }

            // 分页的
            if (rest instanceof IPage) {
                List<Object> items = new ArrayList<>(16);
                for (Object record : ((IPage) rest).getRecords()) {
                    Object item = this.parseObject(record);
                    items.add(item);
                }
                ((IPage) rest).setRecords(items);
                return;
            }

            // 数据列表的
            if (rest instanceof List) {
                List<Object> items = new ArrayList<>();
                for (Object record : ((List) rest)) {
                    Object item = this.parseObject(record);
                    items.add(item);
                }
                // 重新回写值
                ((ApiRest) result).setData(items);
                return;
            }

            // 处理单对象
            Object item = this.parseObject(((ApiRest) result).getData());
            ((ApiRest) result).setData(item);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理数据字典值
     *
     * @param record
     * @return
     */
    public Object parseObject(Object record) {

        if (record == null) {
            return null;
        }

        // 不处理普通数据类型
        if (this.isBaseType(record.getClass())) {
            return record;
        }

        // 转换JSON字符
        String json = JSON.toJSONString(record);
        JSONObject item = JSONObject.parseObject(json);

        for (Field field : Reflections.getAllFields(record)) {

            // 如果是List类型
            if (List.class.isAssignableFrom(field.getType())) {
                try {
                    List list = this.processList(field, item.getObject(field.getName(), List.class));
                    item.put(field.getName(), list);
                    continue;
                } catch (Exception e) {
                    e.printStackTrace();
                }
                continue;
            }

            // 处理普通字段
            if (field.getAnnotation(Dict.class) != null) {
                String code = field.getAnnotation(Dict.class).dicCode();
                String text = field.getAnnotation(Dict.class).dicText();
                String table = field.getAnnotation(Dict.class).dictTable();
                String key = String.valueOf(item.get(field.getName()));

                //翻译字典值对应的txt
                String textValue = this.translateDictValue(code, text, table, key);
                if (StringUtils.isEmpty(textValue)) {
                    textValue = "";
                }
                item.put(field.getName() + "_dictText", textValue);
                continue;
            }

            //日期格式转换
            if (field.getType().getName().equals("java.util.Date") && item.get(field.getName()) != null) {

                // 获取注解
                JsonFormat ann = field.getAnnotation(JsonFormat.class);
                // 格式化方式
                SimpleDateFormat fmt;

                // 使用注解指定的
                if (ann != null && !StringUtils.isEmpty(ann.pattern())) {
                    fmt = new SimpleDateFormat(ann.pattern());
                } else {
                    // 默认时间样式
                    fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                }
                item.put(field.getName(), fmt.format(new Date((Long) item.get(field.getName()))));
                continue;

            }
        }

        return item;
    }

    /**
     * 获得类型为List的值
     *
     * @param field
     * @return
     */
    private List<Object> processList(Field field, List list) {

        // 空判断
        if (list == null || list.size() == 0) {
            return new ArrayList<>();
        }

        // 获得List属性的真实类
        Type genericType = field.getGenericType();
        Class<?> actualType = null;
        if (genericType instanceof ParameterizedType) {
            // 尝试获取数据类型
            ParameterizedType pt = (ParameterizedType) genericType;
            try {
                actualType = (Class) pt.getActualTypeArguments()[0];
            }catch (Exception e){
                return list;
            }
        }

        // 常规列表无需处理
        if (isBaseType(actualType)) {
            return list;
        }

        // 返回列表
        List<Object> result = new ArrayList<>(16);

        for (int i = 0; i < list.size(); i++) {
            // 创建实例-->赋值-->字典处理
            Object data = list.get(i);
            try {
                data = JSON.parseObject(JSON.toJSONString(data), actualType);
            }catch (Exception e){
                // 转换出错不处理
            }

            // 处理后的数据
            Object pds = this.parseObject(data);
            result.add(pds);
        }

        return result;
    }

    /**
     * 翻译实现
     *
     * @param code
     * @param text
     * @param table
     * @param key
     * @return
     */
    private String translateDictValue(String code, String text, String table, String key) {
        if (StringUtils.isEmpty(key)) {
            return null;
        }
        try {
            // 翻译值
            String dictText = null;
            if (!StringUtils.isEmpty(table)) {
                dictText  = sysDictService.findDict(table, text, code, key.trim());
            }

            if (!StringUtils.isEmpty(dictText)) {
                return dictText;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 判断是否基本类型
     *
     * @param clazz
     * @return
     */
    private boolean isBaseType(Class clazz) {


        // 基础数据类型
        if (clazz.equals(java.lang.Integer.class) ||
                clazz.equals(java.lang.Byte.class) ||
                clazz.equals(java.lang.Long.class) ||
                clazz.equals(java.lang.Double.class) ||
                clazz.equals(java.lang.Float.class) ||
                clazz.equals(java.lang.Character.class) ||
                clazz.equals(java.lang.Short.class) ||
                clazz.equals(java.lang.Boolean.class)) {
            return true;
        }

        // String类型
        if (clazz.equals(java.lang.String.class)) {
            return true;
        }

        // 数字
        if (clazz.equals(java.lang.Number.class)) {
            return true;
        }

        return false;
    }


}
