package cd.casic.server.system.plugin.example.web.service.impl;

import cd.casic.plugin.PluginDescriptorStorage;
import cd.casic.plugin.PluginManager;
import cd.casic.plugin.PluginProperties;
import cd.casic.plugin.event.PluginDirCheckEvent;
import cd.casic.plugin.event.PluginLoadedEvent;
import cd.casic.plugin.event.PluginUnloadedEvent;
import cd.casic.plugin.utils.SM4EncryptUtil;
import cd.casic.server.system.plugin.example.web.mapper.PluginStorageMapper;
import cd.casic.server.system.plugin.example.web.service.PluginStorageService;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginDescriptor;
import org.pf4j.PluginState;
import org.pf4j.PluginWrapper;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

@Service
@Slf4j
public class PluginStorageServiceImpl extends ServiceImpl<PluginStorageMapper, PluginDescriptorStorage> implements PluginStorageService {
    @Resource
    private PluginManager pluginManager;
    @Resource
    private PluginProperties pluginProperties;

    private Boolean Cleaned = false;

    @EventListener
    public void initializePlugins(ApplicationStartedEvent event) {
        pluginManager.unloadPlugins();
        Path pluginRoot = Paths.get(pluginProperties.getPluginsRoot());
        List<PluginDescriptorStorage> list = this.list();
        if (ObjectUtil.isNotEmpty(list)) {
            if (!list.get(0).getPluginDirPath().equals(pluginProperties.getPluginsRoot())) {
                this.removeBatchByIds(list);
            }
            list.stream()
                    .filter(pluginDescriptorStorage -> Paths.get(pluginDescriptorStorage.getPath()).startsWith(pluginRoot)
                            && SM4EncryptUtil.checkLicense(pluginDescriptorStorage.getLicense(), pluginDescriptorStorage.getPluginId()))
                    .forEach(pluginDescriptorStorage -> {
                        Path pluginPath = Paths.get(pluginDescriptorStorage.getPath());
                        String pluginId = pluginManager.loadPlugin(pluginPath);
                        if (PluginDescriptorStorage.EnableStatus.ENABLE.getCode().equals(pluginDescriptorStorage.getEnable())) {
                            pluginManager.startPlugin(pluginId);
                        }
                    });
//            }
        }

    }

    @EventListener
    public void pluginDirCheck(PluginDirCheckEvent event) throws IOException {
//        // 跟之前工作目录路径不同就清空数据库
//        String lastDirTxtPath = pluginProperties.getLastDirTxtPath();
//        String pluginsRoot = pluginProperties.getPluginsRoot();
//        String line = null;
//
//        FileReader fileReader = new FileReader(lastDirTxtPath);
//        BufferedReader bufferedReader = new BufferedReader(fileReader);
//        line = bufferedReader.readLine();
//        bufferedReader.close();
//        fileReader.close();
//
//        if (!line.equals(pluginsRoot)){
//            if (!Cleaned){
//                this.remove(new LambdaQueryWrapper<PluginDescriptorStorage>());
//                Cleaned = true;
//                FileWriter fileWriter = new FileWriter(lastDirTxtPath);
//                BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//                bufferedWriter.write(pluginsRoot);
//                bufferedWriter.flush();
//                bufferedWriter.close();
//                fileWriter.close();
//            }
//        }

    }

    @EventListener
    public void insertPlugin(PluginLoadedEvent event) {
        PluginWrapper pluginWrapper = event.getPluginInfo().getPluginWrapper();
        PluginDescriptorStorage pluginDescriptorStorage = convert(pluginWrapper);
        if (this.getById(pluginDescriptorStorage.getPluginId()) != null
                || !SM4EncryptUtil.checkLicense(pluginDescriptorStorage.getLicense()
                , pluginDescriptorStorage.getPluginId())) return;
        this.save(pluginDescriptorStorage);
    }

    @EventListener
    public void deletePlugin(PluginUnloadedEvent event) {
        PluginWrapper pluginWrapper = event.getPluginInfo().getPluginWrapper();
        this.remove(new LambdaQueryWrapper<PluginDescriptorStorage>()
                .eq(PluginDescriptorStorage::getPluginId, pluginWrapper.getPluginId()));
    }

    public PluginDescriptorStorage convert(PluginWrapper pluginWrapper) {
        PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
        return PluginDescriptorStorage.builder()
                .pluginId(pluginDescriptor.getPluginId())
                .pluginClass(pluginDescriptor.getPluginClass())
                .pluginDescription(pluginDescriptor.getPluginDescription())
                .license(pluginDescriptor.getLicense())
                .provider(pluginDescriptor.getProvider())
                .version(pluginDescriptor.getVersion())
                .dependencies(pluginDescriptor.getDependencies())
                .requires(pluginDescriptor.getRequires())
                .enable(pluginWrapper.getPluginState().equals(PluginState.DISABLED) ?
                        PluginDescriptorStorage.EnableStatus.DISABLE.getCode() :
                        PluginDescriptorStorage.EnableStatus.ENABLE.getCode())
                .path(pluginWrapper.getPluginPath().toString())
                .pluginDirPath(pluginProperties.getPluginsRoot())
                .build();
    }
}
