package com.tzy.framework.aspectj;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzy.common.annotation.Desensit;
import com.tzy.common.annotation.DesensitMethod;
import com.tzy.common.core.domain.BaseEntity;
import com.tzy.common.enums.DesensitType;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.StringUtils;
import com.tzy.common.utils.security.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

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

@Slf4j
@Aspect
@Component
public class DesensitAspect {

    // 配置织入点
    @Pointcut("@annotation(com.tzy.common.annotation.DesensitMethod)")
    public void logPointCut()
    {
    }

    /**
     *
     * @param 
     */
//    @AfterReturning("execution(public * com.poyee.*.service.impl.*(..))")
    @AfterReturning(pointcut = "logPointCut()",returning = "result")
    public Object doAfter(JoinPoint joinPoint, JSONObject result)
    {
        try {
            DesensitMethod desensitMethod = getAnnotationLog(joinPoint);
            if(desensitMethod.desensit()){
                Object obj = result.get("data");
                result.put("data",setDesensitData(obj));
            }
            log.info(" 返回参数：{} ",result);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Object setDesensitData(Object obj){
        JSONObject json = new JSONObject();
        try {
            if(null == obj){
                return null;
            }
            if(obj.getClass().getName().indexOf("ArrayList") > 0){
                List<Object> objlist = (List<Object>) obj;
                JSONArray jsonArray = new JSONArray();
                if(!objlist.isEmpty()){
                    objlist.forEach(item->{
                        jsonArray.add(setDesensitData(item));
                    });
                    return jsonArray;
                }
            } else {
                json = (JSONObject) JSONObject.toJSON(obj);
                JSONObject finalJson = json;
                Arrays.stream(obj.getClass().getDeclaredFields()).forEach(field -> {
                    field.setAccessible(true);
                    Desensit annotation = field.getAnnotation(Desensit.class);
                    if (null != annotation) {
                        DesensitType type = annotation.type();
                        if (type.equals(DesensitType.NULL)) {
                            finalJson.remove(field.getName());
                        }else if(type.equals(DesensitType.DEFAULT)){
                            //脱敏操作
                            try {
                                String value = StringUtils.desenstiseStr((String) field.get(obj), 4);
                                finalJson.put(field.getName(),value);
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }else if (type.equals(DesensitType.MD5)){
                            //MD5加密
                            try {
                                finalJson.put(field.getName(), Md5Utils.hash((String) field.get(obj)));
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                });
                BaseEntity.types.forEach(s -> {
                    finalJson.remove(s);
                });
                json = finalJson;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("数据转换异常[1001]！");
        }
        return json;
    }


    /**
     * 是否存在注解，如果存在就获取
     */
    private DesensitMethod getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(DesensitMethod.class);
        }
        return null;
    }
}
