package com.jiuzhekan.cbkj.common.interceptor.tianan;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.defaults.DefaultSqlSession;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * MybatisEntrIntercept
 * <p>
 * 杭州聪宝科技有限公司
 * <p>
 *
 * @author guowei
 * @date 2021/4/8 10:32
 */
@Slf4j
@Intercepts({
        @Signature(
                type = Executor.class,
                method = "update",
                args = {MappedStatement.class, Object.class}
        )
})
public class TianAnEncryptIntercept implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.info("===========TianAnEncryptIntercept===========");

        encryptParams(invocation.getArgs()[1]);

        return invocation.proceed();
    }

    /**
     * 加密参数
     *
     * @param parameter 参数
     * @author guowei
     * @date 2021/4/8
     */
    private void encryptParams(Object parameter) {
        if (parameter instanceof String) {

        } else if (parameter instanceof DefaultSqlSession.StrictMap) {
            DefaultSqlSession.StrictMap<Object> strictMap = (DefaultSqlSession.StrictMap<Object>) parameter;
            for (Map.Entry<String, Object> entry : strictMap.entrySet()) {
                if (entry.getKey().contains("collection")) {

                } else if (entry.getKey().contains("list")) {
                    for (Object o : (List) entry.getValue()) {
                        encryptBean(o);
                    }
                }
            }
            // 多参数
        } else if (parameter instanceof MapperMethod.ParamMap) {
            MapperMethod.ParamMap<Object> paramMap = (MapperMethod.ParamMap<Object>) parameter;
            // 解析每一个参数
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                // 判断不需要解析的类型 不解析map
                if (entry.getValue() instanceof Map || entry.getKey().contains("param")) {

                } else if (entry.getValue() instanceof String) {

                } else if (entry.getValue() instanceof List) {
                    for (Object o : (List) entry.getValue()) {
                        encryptBean(o);
                    }
                } else {
                    encryptBean(entry.getValue());
                }
            }
        } else { // bean
            encryptBean(parameter);
        }
    }

    /**
     * 加密对象
     *
     * @param bean 对象
     * @author guowei
     * @date 2021/4/8
     */
    private void encryptBean(Object bean) {
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                if (field.getType() == List.class) {
                    field.setAccessible(true);
                    List list = (List) field.get(bean);
                    for (Object o : list) {
                        encryptBean(o);
                    }
                } else if (field.isAnnotationPresent(TianAnEncryptField.class)) {

                    field.setAccessible(true);
                    Object value = field.get(bean);
                    if (value != null) {
                        String encrypt = TianAnUtils.encrypt(value.toString());
                        field.set(bean, encrypt);
                    }
                }
            } catch (Exception ignored) {
            }
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
