package org.springblade.common.utils;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.base.BaseService;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author: Silent
 * @Description 使用该对象去调用BaseService方法可以忽略租户
 * @Date: Created in 15:49 2021/10/12
 * @Modified By:
 */
@Component
@TenantIgnore
public class TenantIgnoreUtil<S extends BaseService<T>,T extends BaseEntity>{

	@TenantIgnore
	public boolean deleteLogic(S s, @NotEmpty List ids) {
		return s.deleteLogic(ids);
	}

	@TenantIgnore
	public boolean changeStatus(S s, @NotEmpty List ids, Integer status) {
		return s.changeStatus(ids, status);
	}

	@TenantIgnore
	public boolean save(S s, T entity) {
		return s.save(entity);
	}

	@TenantIgnore
	public boolean saveBatch(S s, Collection entityList) {
		return s.saveBatch(entityList);
	}

	@TenantIgnore
	public boolean saveBatch(S s, Collection entityList, int batchSize) {
		return s.saveBatch(entityList, batchSize);
	}

	@TenantIgnore
	public boolean saveOrUpdateBatch(S s, Collection entityList) {
		return s.saveOrUpdateBatch(entityList);
	}

	@TenantIgnore
	public boolean saveOrUpdateBatch(S s, Collection entityList, int batchSize) {
		return s.saveOrUpdateBatch(entityList, batchSize);
	}

	@TenantIgnore
	public boolean removeById(S s, Serializable id) {
		return s.removeById(id);
	}

	@TenantIgnore
	public boolean remove(S s, Wrapper queryWrapper) {
		return s.remove(queryWrapper);
	}

	@TenantIgnore
	public boolean updateById(S s, T entity) {
		return s.updateById(entity);
	}

	@TenantIgnore
	public boolean update(S s, Wrapper updateWrapper) {
		return s.update(updateWrapper);
	}

	@TenantIgnore
	public boolean update(S s, T entity, Wrapper updateWrapper) {
		return s.update(entity, updateWrapper);
	}

	@TenantIgnore
	public boolean updateBatchById(S s, Collection entityList) {
		return s.updateBatchById(entityList);
	}

	@TenantIgnore
	public boolean removeByIds(S s, Collection idList) {
		return s.removeByIds(idList);
	}

	@TenantIgnore
	public boolean removeByMap(S s, Map columnMap) {
		return s.removeByMap(columnMap);
	}

	@TenantIgnore
	public boolean updateBatchById(S s, Collection entityList, int batchSize) {
		return s.updateBatchById(entityList, batchSize);
	}

	@TenantIgnore
	public boolean saveOrUpdate(S s, T entity) {
		return s.saveOrUpdate(entity);
	}

	@TenantIgnore
	public T getById(S s, Serializable id) {
		return s.getById(id);
	}

	@TenantIgnore
	public T getOne(S s, Wrapper<T> queryWrapper) {
		return s.getOne(queryWrapper);
	}

	@TenantIgnore
	public List listByMap(S s, Map columnMap) {
		return s.listByMap(columnMap);
	}

	@TenantIgnore
	public List listByIds(S s, Collection idList) {
		return s.listByIds(idList);
	}

	@TenantIgnore
	public T getOne(S s, Wrapper<T> queryWrapper, boolean throwEx) {
		return s.getOne(queryWrapper, throwEx);
	}

	@TenantIgnore
	public Map<String, Object> getMap(S s, Wrapper<T> queryWrapper) {
		return s.getMap(queryWrapper);
	}

	@TenantIgnore
	public int count(S s) {
		return s.count();
	}

	@TenantIgnore
	public int count(S s, Wrapper queryWrapper) {
		return s.count(queryWrapper);
	}

	@TenantIgnore
	public List list(S s, Wrapper queryWrapper) {
		return s.list(queryWrapper);
	}

	@TenantIgnore
	public List list(S s) {
		return s.list();
	}

	@TenantIgnore
	public List<Map<String, Object>> listMaps(S s, Wrapper queryWrapper) {
		return s.listMaps(queryWrapper);
	}

	@TenantIgnore
	public List<Map<String, Object>> listMaps(S s) {
		return s.listMaps();
	}

	@TenantIgnore
	public List<Object> listObjs(S s) {
		return s.listObjs();
	}

	@TenantIgnore
	public List<T> listObjs(S s, Wrapper queryWrapper) {
		return s.listObjs(queryWrapper);
	}

	@TenantIgnore
	public <P extends IPage<Map<String, Object>>> P pageMaps(S s, P page) {
		return s.pageMaps(page);
	}

	@TenantIgnore
	public <P extends IPage<Map<String, Object>>> P pageMaps(S s, P page, Wrapper<T> queryWrapper) {
		return s.pageMaps(page, queryWrapper);
	}

	@TenantIgnore
	public List listObjs(S s, Wrapper queryWrapper, Function mapper) {
		return s.listObjs(queryWrapper, mapper);
	}

	@TenantIgnore
	public List listObjs(S s, Function mapper) {
		return s.listObjs(mapper);
	}

	@TenantIgnore
	public <P extends IPage<T>> P page(S s, P page) {
		return s.page(page);
	}

	@TenantIgnore
	public <P extends IPage<T>> P page(S s, P page, Wrapper<T> queryWrapper) {
		return s.page(page, queryWrapper);
	}

	@TenantIgnore
	public BaseMapper getBaseMapper(S s) {
		return s.getBaseMapper();
	}

	@TenantIgnore
	public Class getEntityClass(S s) {
		return s.getEntityClass();
	}

	@TenantIgnore
	public QueryChainWrapper query(S s) {
		return s.query();
	}

	@TenantIgnore
	public LambdaQueryChainWrapper lambdaQuery(S s) {
		return s.lambdaQuery();
	}

	@TenantIgnore
	public KtQueryChainWrapper ktQuery(S s) {
		return s.ktQuery();
	}

	@TenantIgnore
	public KtUpdateChainWrapper ktUpdate(S s) {
		return s.ktUpdate();
	}

	@TenantIgnore
	public UpdateChainWrapper update(S s) {
		return s.update();
	}

	@TenantIgnore
	public LambdaUpdateChainWrapper lambdaUpdate(S s) {
		return s.lambdaUpdate();
	}

	@TenantIgnore
	public boolean saveOrUpdate(S s, T entity, Wrapper updateWrapper) {
		return s.saveOrUpdate(entity, updateWrapper);
	}

	@TenantIgnore
	public Object getObj(S s, Wrapper<T> queryWrapper, Function mapper) {
		return s.getObj(queryWrapper, mapper);
	}

	/**
	 * 通过反射代理执行
	 * @param s
	 * @param funName
	 * @param tClass
	 * @param Es
	 * @return
	 */
	@TenantIgnore
	public Object invoke(S s,String funName,Class<S> tClass,Object... Es){
		try {
			Method declaredMethod = s.getClass().getDeclaredMethod(funName,tClass);
			return declaredMethod.invoke(s,Es);
		} catch (NoSuchMethodException t) {
			t.printStackTrace();
		} catch (InvocationTargetException t) {
			t.printStackTrace();
		} catch (IllegalAccessException t) {
			t.printStackTrace();
		}
		return null;
	}

	@TenantIgnore
	public Object invoke(S s,Method method,Object... Es){
		try {
			return method.invoke(s,Es);
		} catch (InvocationTargetException t) {
			t.printStackTrace();
		} catch (IllegalAccessException t) {
			t.printStackTrace();
		}
		return null;
	}
}
