package com.changhu.support.mybatisplus.config;

import cn.hutool.core.util.ReflectUtil;
import com.changhu.support.mybatisplus.annotation.DataScope;
import com.changhu.support.mybatisplus.handler.permission.AbstractDataPermissionHandler;
import org.jetbrains.annotations.NotNull;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author 20252
 * @createTime 2024/8/8 下午4:08
 * @desc 数据权限管理器
 */
@Component
public class DataScopeManage implements BeanPostProcessor {

    /**
     * mappedStatementId 对应的 权限处理器
     */
    private static final Map<String, AbstractDataPermissionHandler> dataScopeMethods = new HashMap<>();

    /**
     * 可以向权限处理器传递参数
     */
    private static final ThreadLocal<Object> paramsHolder = new ThreadLocal<>();

    public static void setParams(Object params) {
        paramsHolder.set(params);
    }

    public static Object getParams() {
        return paramsHolder.get();
    }

    public void removeParams() {
        paramsHolder.remove();
    }

    /**
     * 获取数据权限处理器
     *
     * @param mappedStatementId key
     * @return 权限处理器
     */
    public static AbstractDataPermissionHandler getDataScopeHandler(String mappedStatementId) {
        return dataScopeMethods.get(mappedStatementId);
    }

    @Override
    public Object postProcessBeforeInitialization(@NotNull Object bean, @NotNull String beanName) throws BeansException {
        if (bean instanceof MapperFactoryBean) {
            Class<?> mapperInterface = ((MapperFactoryBean<?>) bean).getMapperInterface();
            Method[] methods = mapperInterface.getDeclaredMethods();
            for (Method method : methods) {
                Optional.ofNullable(method.getAnnotation(DataScope.class))
                        .ifPresent(dataScope -> dataScopeMethods.put(
                                mapperInterface.getName() + "." + method.getName(),
                                ReflectUtil.newInstance(dataScope.permissionHandler()
                                )));
            }
        }
        return bean;
    }

}
