package com.bonus.core.common.encrypt;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
import java.util.Properties;

@Component
@Intercepts({@Signature(
   type = ResultSetHandler.class,
   method = "handleResultSets",
   args = {Statement.class}
)})
public class ResultDecryptInterceptor implements Interceptor {
   private static final Logger log = LoggerFactory.getLogger(ResultDecryptInterceptor.class);
   @Autowired
   LeNiuDataHandler dataHandler;
   @Autowired
   private DataEncDecProperties dataEncDecProperties;

   public Object intercept(Invocation invocation) throws Throwable {
      if (!this.dataEncDecProperties.isEncrypted()) {
         return invocation.proceed();
      } else {
         Object resultObject = invocation.proceed();
         if (Objects.isNull(resultObject)) {
            return resultObject;
         } else {
            if (resultObject instanceof ArrayList) {
               ArrayList<?> resultList = (ArrayList)resultObject;
               if (CollectionUtil.isEmpty(resultList)) {
                  return resultObject;
               }

               if (ObjectUtil.isNull(resultList.get(0))) {
                  return resultObject;
               }

               LeNiuDecryptDataProcess decryptData = this.getAnnotation(resultList.get(0));
               if (ObjectUtil.isNull(decryptData)) {
                  return resultObject;
               }

               Iterator var5 = resultList.iterator();

               while(var5.hasNext()) {
                  Object result = var5.next();
                  this.resultProcessOne(result);
               }
            } else {
               LeNiuDecryptDataProcess decryptData = this.getAnnotation(resultObject);
               if (ObjectUtil.isNull(decryptData)) {
                  return resultObject;
               }

               this.resultProcessOne(resultObject);
            }

            return resultObject;
         }
      }
   }

   public void resultProcessOne(Object result) throws IllegalAccessException {
      Field[] fields = result.getClass().getDeclaredFields();
      if (fields.length > 0) {
         this.dataHandler.resultProcess(result);
      }

   }

   private LeNiuDecryptDataProcess getAnnotation(Object object) {
      Class<?> objectClass = object.getClass();
      return (LeNiuDecryptDataProcess)AnnotationUtils.findAnnotation(objectClass, LeNiuDecryptDataProcess.class);
   }

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

   public void setProperties(Properties properties) {
   }
}
