package com.ibeetl.admin.core.conf.beetl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibeetl.admin.core.conf.JacksonConfig;
import com.ibeetl.admin.core.conf.beetl.handler.DateTypeHandler;
import com.ibeetl.admin.core.conf.beetl.handler.DictTypeHandler;
import com.ibeetl.admin.core.conf.beetl.handler.ZonedDateTimeTypeHandler;
import com.ibeetl.admin.core.conf.beetl.processor.JsonBeanProcessor;
import com.ibeetl.admin.core.entity.DictType;
import com.ibeetl.admin.core.rbac.DataAccessFactory;
import com.ibeetl.admin.core.service.CorePlatformService;
import com.ibeetl.admin.core.util.beetl.DictQueryFunction;
import com.ibeetl.admin.core.util.beetl.FileFunction;
import com.ibeetl.admin.core.util.beetl.FunAccessUrlFunction;
import com.ibeetl.admin.core.util.beetl.FunFunction;
import com.ibeetl.admin.core.util.beetl.MenuFunction;
import com.ibeetl.admin.core.util.beetl.OrgFunction;
import com.ibeetl.admin.core.util.beetl.RoleFunction;
import com.ibeetl.admin.core.util.beetl.SearchCondtionFunction;
import com.ibeetl.admin.core.util.beetl.SysFunctionTreeFunction;
import java.sql.JDBCType;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.beetl.core.GroupTemplate;
import org.beetl.ext.simulate.JsonUtil;
import org.beetl.ext.simulate.WebSimulate;
import org.beetl.sql.core.Interceptor;
import org.beetl.sql.core.InterceptorContext;
import org.beetl.sql.core.SqlId;
import org.beetl.sql.core.engine.SQLParameter;
import org.beetl.sql.core.engine.SQLPlaceholderST;
import org.beetl.sql.core.mapping.type.JavaSqlTypeHandler;
import org.beetl.sql.ext.DebugInterceptor;
import org.beetl.sql.starter.SQLManagerCustomize;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

@Configuration
@AutoConfigureAfter(JacksonConfig.class)
public class BeetlConf {

  @Autowired
  Environment env;

  @Autowired
  CorePlatformService platFormService;

  @Autowired
  OrgFunction orgFunction;

  @Autowired
  SysFunctionTreeFunction sysFunctionTreeFunction;

  @Autowired
  DictQueryFunction dictDownQueryFunction;

  @Autowired
  RoleFunction roleFunction;

  @Autowired
  FileFunction fileFunction;

  @Autowired
  SearchCondtionFunction searchCondtionFunction;

  @Autowired
  DataAccessFactory dataAccessFactory;

  @Autowired
  ApplicationContext applicationContext;

  @Autowired
  FunFunction funFunction;

  @Autowired
  FunAccessUrlFunction funAccessUrlFunction;

  @Autowired
  MenuFunction menuFunction;


  /**
   * 对BeetlSql 的多数据源中每个数据源单独自定义配置
   */
  @Bean
  public SQLManagerCustomize beetlSqlMutipleSourceCustomize() {

    SQLPlaceholderST.textFunList.add("mapping");
    return (dataSource, manager) -> {
      /*bean转换处理器*/
//      JsonBeanProcessor jsonBeanProcessor = new JsonBeanProcessor();
//      manager.setDefaultBeanProcessors(jsonBeanProcessor);
      /*类型处理器*/
      Map<Class, JavaSqlTypeHandler> typeHandlerMap =
          manager.getDefaultBeanProcessors().getHandlers();
      /*Java bean的属性类型处理器，从数据库类型转化到属性Date类型*/
      typeHandlerMap.remove(Date.class);
      typeHandlerMap.put(Date.class, new DateTypeHandler());
      typeHandlerMap.put(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
      typeHandlerMap.put(DictType.class, new DictTypeHandler());
      /*拦截器*/
      manager.setInters(
          new Interceptor[]{new StarterDebugInterceptor(), new TypeHandlerInterceptor()});
    };
  }

  static class StarterDebugInterceptor extends DebugInterceptor {

    private Logger logger = LoggerFactory.getLogger("beetlsql");

    /**
     * 将内置生成的SQL排除打印
     */
    @Override
    protected boolean isSimple(SqlId sqlId) {
      //      if (sqlId.indexOf("_gen_") != -1) {
      //        return true;
      //      } else {
      //        return false;
      //      }
      return super.isSimple(sqlId);
    }

  }

}

/**
 * Class TypeHandlerInterceptor : <br>
 * 描述：预计做类型处理工厂拦截器
 *
 * @author 一日看尽长安花 Created on 2020/2/3
 */
class TypeHandlerInterceptor implements Interceptor {

  @Override
  public void before(InterceptorContext ctx) {

    List<SQLParameter> paras = ctx.getExecuteContext().sqlResult.jdbcPara;
    for (SQLParameter para : paras) {
      if (para.value instanceof Date) {
        para.value = ((Date) para.value).getTime();
        para.setJdbcType(JDBCType.BIGINT.getVendorTypeNumber());
      }
    }
  }

  @Override
  public void after(InterceptorContext ctx) {

  }

  @Override
  public void exception(InterceptorContext ctx, Exception ex) {

  }

}
