/**
 * 
 */
package org.springblade.core.mp.tenant;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springblade.core.mp.properties.TenantProperties;

import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

/**
 * @author wookvn
 *
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class PlatomixTenantInterceptor extends TenantLineInnerInterceptor {

	/**
	 * 租户处理器
	 */
	private TenantLineHandler tenantLineHandler;
	/**
	 * 租户配置文件
	 */
	private TenantProperties tenantProperties;

	@Override
	public void setTenantLineHandler(TenantLineHandler tenantLineHandler) {
		super.setTenantLineHandler(tenantLineHandler);
		this.tenantLineHandler = tenantLineHandler;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
			ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
		if (InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) {
			return;
		}
		if(tenantProperties.getDefaultExclusionMapperIds().stream().anyMatch(f -> ms.getId().contains(f)) ||
				tenantProperties.getExclusionMapperIds().stream().anyMatch(f -> ms.getId().contains(f))) {
			return;
		}
		PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
		if(mpBs.sql().contains(String.format("%s = ?", tenantLineHandler.getTenantIdColumn()))) { //如果where条件中已存在tenant_id字段，不再拼接
			return;
		}
		mpBs.sql(parserSingle(mpBs.sql(), null));
	}

	@Override
	public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
		PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
		MappedStatement ms = mpSh.mappedStatement();
		SqlCommandType sct = ms.getSqlCommandType();
		if(tenantProperties.getDefaultExclusionMapperIds().stream().anyMatch(f -> ms.getId().contains(f)) ||
				tenantProperties.getExclusionMapperIds().stream().anyMatch(f -> ms.getId().contains(f))) {
			return;
		}
		if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
			if (InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) {
				return;
			}
			PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
			mpBs.sql(parserMulti(mpBs.sql(), null));
		}
	}
}
