package com.qiaoba.common.database.interceptor;

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectFactory;
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel;
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import com.qiaoba.common.base.util.AnnotationUtil;
import com.qiaoba.common.database.annotation.SelectOneRow;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * 查询一条
 * 因为Oracle 不支持 limit 1 写法, 故调用MP的分页方言处理
 *
 * @author ailanyin
 * @version 1.0
 * @since 2023/6/21 8:53
 */
public class SelectOneRowInterceptor implements InnerInterceptor {

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        if (AnnotationUtil.hasAnnotation(ms.getId(), SelectOneRow.class)) {
            String buildSql = boundSql.getSql();
            IDialect dialect = DialectFactory.getDialect(JdbcUtils.getDbType(executor));
            DialectModel model = dialect.buildPaginationSql(buildSql, 0, 1);
            replaceSql(ms, boundSql, model);
        }
    }

    private void replaceSql(MappedStatement ms, BoundSql boundSql, DialectModel model) {
        PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
        final Configuration configuration = ms.getConfiguration();
        List<ParameterMapping> mappings = mpBoundSql.parameterMappings();
        Map<String, Object> additionalParameter = mpBoundSql.additionalParameters();
        model.consumers(mappings, configuration, additionalParameter);
        mpBoundSql.sql(model.getDialectSql());
        mpBoundSql.parameterMappings(mappings);
    }

}
