package cn.axzo.msg.center.message.service.todo.mybatis;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.sql.Statement;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * @author yanglin
 */
@Slf4j
@Intercepts(value = {
        @Signature(type = StatementHandler.class, method = "parameterize", args = {Statement.class})
})
public class CollectSQLInterceptor implements Interceptor {

    private static final ThreadLocal<CollectSqlConfig> LOCAL = new ThreadLocal<>();

    public static void enableCollectSQL(CollectSqlConfig value) {
        LOCAL.set(value);
    }

    public static void disableCollectSQL() {
        LOCAL.remove();
    }

    public static Optional<String> getSQL() {
        CollectSqlConfig info = LOCAL.get();
        return info == null ? Optional.empty() : Optional.ofNullable(info.sql);
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();
        CollectSqlConfig info = LOCAL.get();
        // collect for first stmt
        if (info != null && StringUtils.isBlank(info.sql)) {
            try {
                info.sql = SQLAccessor.getSQL(invocation);
            } catch (Exception e) {
                log.warn("error get sql", e);
            }
        }
        return result;
    }

    public static void maybeBuildSqlSelf(Supplier<String> provider) {
        CollectSqlConfig info = LOCAL.get();
        // collect for first stmt
        if (info != null && StringUtils.isBlank(info.sql) && info.tryBuildSqlSelf) {
            try {
                info.sql = provider.get();
            } catch (Exception e) {
                log.warn("error build sql self", e);
            }
        }
    }

    @RequiredArgsConstructor
    public static class CollectSqlConfig {
        private final boolean tryBuildSqlSelf;
        private String sql;
    }

}