package cd.casic.plugin.core.register;

import cd.casic.plugin.core.BasePlugin;
import cd.casic.plugin.core.register.filter.PluginClassFilter;
import cd.casic.plugin.core.register.filter.impl.*;
import cd.casic.plugin.dataobject.dao.PluginFacadeMemoryCache;
import cd.casic.plugin.dataobject.pojo.PluginInfo;
import cd.casic.plugin.function.IPluginProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static cd.casic.plugin.utils.PluginsUtils.scanClassPackageName;

/**
 * @description: TODO
 * @author: mianbin
 * @date: 2025/5/22 17:17
 * @version: 1.0
 */
@Slf4j
@Component
public class ClassGroupProcessor implements IPluginProcessor {

    private final List<PluginClassFilter> classFilters = new ArrayList<>();

    @Override
    public void initialize() throws Exception {
        classFilters.add(new BasicBeanFilter());
        classFilters.add(new ControllerFilter());
        classFilters.add(new DataBaseEntityFilter());
        classFilters.add(new MapperFilter());
        classFilters.add(new PluginConfigurationFilter());
        classFilters.add(new WebSocketFilter());
        log.info("Start to hand the ClassGroup Class for plugin");
    }

    @Override
    public void registry(PluginInfo plugin) throws Exception {
        List<Class<?>> classList = new ArrayList<>();
        Set<String> classPackageName = scanClassPackageName(plugin.getBasePlugin().scanPackage(), plugin.getBasePlugin().getWrapper());
        for (String packageName : classPackageName) {
            ClassLoader loader = PluginFacadeMemoryCache.getPluginClassLoader(plugin.getPluginId());
            log.info("Load class {} using classloader {} for plugin {}", packageName, PluginFacadeMemoryCache.getPluginInfo(plugin.getPluginId()), plugin.getPluginId());
            Class<?> clazz = loader.loadClass(packageName);
            if (!BasePlugin.class.isAssignableFrom(clazz)) {
                classList.add(clazz);
            }
        }
        plugin.setClassList(classList);
        List<Class<?>> pluginClassList = plugin.getClassList().stream().filter(item -> !item.isInterface()).collect(Collectors.toList());
        if (!pluginClassList.isEmpty()) {
            for (Class<?> clazz : pluginClassList) {
                boolean grouped = false;
                for (PluginClassFilter filter : classFilters) {
                    if (filter.filter(clazz)) {
                        log.info("将类 {} 添加到 {} 分组", clazz, filter.groupName());
                        plugin.addGroupClass(filter.groupName(), clazz);
                        grouped = true;
                    }
                }
                if (!grouped) {
                    log.info("类 {} 不属于任何已知分组", clazz);
                    plugin.addGroupClass("unknown", clazz);
                }
            }
        }
    }

    @Override
    public void unRegistry(PluginInfo plugin) throws Exception {
        plugin.getClassList().clear();
    }
}
