package cd.casic.plugin;

import cd.casic.plugin.dataobject.dto.PluginSpecStorage;
import cd.casic.plugin.utils.YamlUnstructuredLoader;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.DevelopmentPluginClasspath;
import org.pf4j.PluginRuntimeException;
import org.pf4j.util.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

/**
 * @description: TODO
 * @author: mianbin
 * @date: 2025/5/12 19:20
 * @version: 1.0
 */
@Slf4j
public class YamlPluginFinder {
    static final DevelopmentPluginClasspath PLUGIN_CLASSPATH = new DevelopmentPluginClasspath();
    public static final String DEFAULT_PROPERTIES_FILE_NAME = "plugin.yaml";
    private final String propertiesFileName;

    public YamlPluginFinder() {
        this(DEFAULT_PROPERTIES_FILE_NAME);
    }

    public YamlPluginFinder(String propertiesFileName) {
        this.propertiesFileName = propertiesFileName;
    }

    public PluginSpecStorage find(Path pluginPath) {
        PluginSpecStorage pluginSpecStorage = readPluginDescriptor(pluginPath);
        Optional.of(pluginSpecStorage.getEnable()).ifPresent(t -> {
            pluginSpecStorage.setEnable(PluginSpecStorage.StatusPhase.PENDING);
        });
        Optional.of(pluginSpecStorage.getPluginDirPath()).ifPresent(pluginSpecStorage::setPluginDirPath);
        return pluginSpecStorage;
    }

    private PluginSpecStorage readPluginDescriptor(Path pluginPath) {
        Path propertiesPath = null;
        try {
            propertiesPath = getManifestPath(pluginPath, propertiesFileName);
            if (propertiesPath == null) {
                throw new PluginRuntimeException("找不到插件 manifest path");
            }
            log.debug("debug下插件的配置文件内容 plugin descriptor in '{}'", propertiesPath);
            if (Files.notExists(propertiesPath)) {
                throw new PluginRuntimeException("Cannot find '{}' path", propertiesPath);
            }
            Resource yamlResource = new FileSystemResource(propertiesPath);
            YamlUnstructuredLoader yamlUnstructuredLoader = new YamlUnstructuredLoader(yamlResource);
            return yamlUnstructuredLoader.load();
        } finally {
            FileUtils.closePath(propertiesPath);
        }
    }

    private Path getManifestPath(Path pluginPath, String propertiesFileName) {
        if (Files.isDirectory(pluginPath)) {
            for (String location : PLUGIN_CLASSPATH.getClassesDirectories()) {
                var path = pluginPath.resolve(location).resolve(propertiesFileName);
                Resource propertyResource = new FileSystemResource(path);
                if (propertyResource.exists()) {
                    return path;
                }
            }
            throw new PluginRuntimeException(
                    "找不到插件配置目录: " + DEFAULT_PROPERTIES_FILE_NAME);
        } else {
            try {
                return FileUtils.getPath(pluginPath, propertiesFileName);
            } catch (IOException e) {
                throw new PluginRuntimeException(e);
            }
        }
    }
}
