package org.example.Impl;


import org.example.Api.LoggerHandler;
import org.example.Entity.BaseResponse.BaseResponse;
import org.example.Entity.Control.Com.SysPoPupMenuBtn;
import org.example.Entity.EventArgs;
import org.example.Entity.System.BillStateEn;
import org.example.Entity.System.ModuleBaseEntity;
import org.example.Enums.SystemEnums;
import org.example.Service.IModuleEvent;
import org.example.Utils.FileUtil;
import org.example.Utils.WebConfigUtil;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

public class ModuleEventImpl extends OptBaseImpl {
    private static final AtomicReference<ModuleEventImpl> instance = new AtomicReference<>(null);

    public static ModuleEventImpl getInstance() {
        if (instance.get() == null) {
            synchronized (ModuleEventImpl.class) {
                if (instance.get() == null) {
                    instance.set(new ModuleEventImpl());
                }
            }
        }
        return instance.get();
    }

    // 事件监听器列表
    private final List<ModuleDataLoadListener> beforeModuleDataLoadListeners = new ArrayList<>();
    private final List<ModuleDataChangeListener> beforeModuleDataChangeListeners = new ArrayList<>();
    private final List<ModuleDataChangeListener> afterModuleDataChangeListeners = new ArrayList<>();
    private final List<ModuleDataChangeListener> beforeModuleDataDeleteListeners = new ArrayList<>();
    private final List<ModuleDataChangeListener> afterModuleDataDeleteListeners = new ArrayList<>();
    private final List<ModuleStateChangeListener> beforeModuleStateChangeListeners = new ArrayList<>();
    private final List<ModuleStateChangeListener> afterModuleStateChangeListeners = new ArrayList<>();
    private final List<ModuleAuditStateChangeListener> beforeModuleAuditStateChangeListeners = new ArrayList<>();
    private final List<ModuleAuditStateChangeListener> afterModuleAuditStateChangeListeners = new ArrayList<>();
    private final List<ModuleContextMenuListener> beforeModuleContextMenuListeners = new ArrayList<>();
    private final List<ModuleContextMenuListener> afterModuleContextMenuListeners = new ArrayList<>();
    private final List<FileUploadListener> beforeUploadFileListeners = new ArrayList<>();
    private final List<FileUploadListener> afterUploadFileListeners = new ArrayList<>();
    private final List<AppListener> appStartListeners = new ArrayList<>();
    private final List<AppListener> appEndListeners = new ArrayList<>();

    private ModuleEventImpl() {
        loadEventHandler();
    }

    private void loadEventHandler() {
        String eventCls = WebConfigUtil.get("ModuleApiHandler", "");
        if (eventCls == null || eventCls.isEmpty()) {
            return;
        }

        String[] classInfos = eventCls.split(";");
        for (String cls : classInfos) {
            if (cls == null || cls.isEmpty() || !cls.contains(",")) {
                continue;
            }

            String[] clsParts = cls.split(",", 2);
            if (clsParts.length < 2 || clsParts[1].isEmpty()) {
                continue;
            }

            String className = clsParts[0].trim();
            String assemblyName = clsParts[1].trim();

            try {
                LoggerHandler.debug(this, "加载程序集: " + assemblyName);

                // 构建程序集路径
                String appPath = System.getProperty("user.dir");
                String assemblyPath = appPath + File.separator + "bin" + File.separator + assemblyName;
                File assemblyFile = new File(assemblyPath);

                if (!assemblyFile.exists()) {
                    LoggerHandler.error(this, "程序集不存在: " + assemblyPath);
                    continue;
                }

                // 加载外部类
                URLClassLoader classLoader = new URLClassLoader(
                        new URL[]{assemblyFile.toURI().toURL()},
                        Thread.currentThread().getContextClassLoader()
                );
                Class<?> eventClass = classLoader.loadClass(className);
                IModuleEvent eventOper = (IModuleEvent) eventClass.getDeclaredConstructor().newInstance();

                if (eventOper != null) {
                    LoggerHandler.debug(this, "加载程序集实例: " + className);
                    registerListener(eventOper);
                } else {
                    LoggerHandler.error(this, "未能实例化事件类: " + className);
                }
            } catch (MalformedURLException e) {
                LoggerHandler.error(this, "程序集路径错误: " + assemblyName + " - " + e.getMessage());
            } catch (ClassNotFoundException e) {
                LoggerHandler.error(this, "未找到事件类: " + className + " - " + e.getMessage());
            } catch (Exception e) {
                LoggerHandler.error(this, "加载事件程序集出错: " + cls + " - " + e.getMessage());
            }
        }
    }

    private void registerListener(IModuleEvent listener) {
        beforeModuleDataLoadListeners.add(listener::beforeModuleDataLoad);
        beforeModuleDataChangeListeners.add(listener::beforeModuleDataChange);
        afterModuleDataChangeListeners.add(listener::afterModuleDataChange);
        beforeModuleDataDeleteListeners.add(listener::beforeModuleDataDelete);
        afterModuleDataDeleteListeners.add(listener::afterModuleDataDelete);
        beforeModuleStateChangeListeners.add(listener::beforeModuleStateChange);
        afterModuleStateChangeListeners.add(listener::afterModuleStateChange);
        beforeModuleAuditStateChangeListeners.add(listener::beforeModuleAuditStateChange);
        afterModuleAuditStateChangeListeners.add(listener::afterModuleAuditStateChange);
        beforeModuleContextMenuListeners.add(listener::beforeModuleContextMenu);
        afterModuleContextMenuListeners.add(listener::afterModuleContextMenu);
        beforeUploadFileListeners.add(listener::beforeUploadFile);
        afterUploadFileListeners.add(listener::afterUploadFile);
        appStartListeners.add(listener::appStart);
        appEndListeners.add(listener::appEnd);
    }

    // 事件调用方法
    public void callBeforeModuleDataLoad(String moduleId) {
        ModuleBaseEntity module = new ModuleBaseEntity();
        module.setModuleId(moduleId);
        beforeModuleDataLoadListeners.forEach(listener -> listener.onModuleDataLoad(module));
    }

    public void callBeforeModuleDataChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response) {
        beforeModuleDataChangeListeners.forEach(listener -> listener.onModuleDataChange(module, aType, response));
    }

    public void callAfterModuleDataChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response) {
        afterModuleDataChangeListeners.forEach(listener -> listener.onModuleDataChange(module, aType, response));
    }

    public void callBeforeModuleDataDelete(ModuleBaseEntity module, BaseResponse response) {
        beforeModuleDataDeleteListeners.forEach(listener -> listener.onModuleDataChange(module, SystemEnums.ActionType.Delete, response));
    }

    public void callAfterModuleDataDelete(ModuleBaseEntity module, BaseResponse response) {
        afterModuleDataDeleteListeners.forEach(listener -> listener.onModuleDataChange(module, SystemEnums.ActionType.Delete, response));
    }

    public void callBeforeModuleStateChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response) {
        beforeModuleStateChangeListeners.forEach(listener -> listener.onModuleStateChange(module, aType, response));
    }

    public void callAfterModuleStateChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response) {
        afterModuleStateChangeListeners.forEach(listener -> listener.onModuleStateChange(module, aType, response));
    }

    public void callBeforeModuleAuditStateChange(ModuleBaseEntity module, BillStateEn stateEn, BaseResponse response) {
        beforeModuleAuditStateChangeListeners.forEach(listener -> listener.onModuleAuditStateChange(module, stateEn, response));
    }

    public void callAfterModuleAuditStateChange(ModuleBaseEntity module, BillStateEn stateEn, BaseResponse response) {
        afterModuleAuditStateChangeListeners.forEach(listener -> listener.onModuleAuditStateChange(module, stateEn, response));
    }

    public void callBeforeModuleContextMenu(SysPoPupMenuBtn btn, BaseResponse response) {
        beforeModuleContextMenuListeners.forEach(listener -> listener.onModuleContextMenu(btn, response));
    }

    public void callAfterModuleContextMenu(SysPoPupMenuBtn btn, BaseResponse response) {
        afterModuleContextMenuListeners.forEach(listener -> listener.onModuleContextMenu(btn, response));
    }

    public void callBeforeUploadFile(FileUtil.PathInfo info, BaseResponse response) {
        beforeUploadFileListeners.forEach(listener -> listener.onFileUpload(info, response));
    }

    public void callAfterUploadFile(FileUtil.PathInfo info, BaseResponse response) {
        afterUploadFileListeners.forEach(listener -> listener.onFileUpload(info, response));
    }

    public void appStart(Object sender, EventArgs e) throws SQLException {
        new UpdateImpl().checkUpdate();
        appStartListeners.forEach(listener -> listener.onAppEvent(sender, e));
    }

    public void appEnd(Object sender, EventArgs e) throws SQLException {
        new UpdateImpl().checkUpdate();
        appEndListeners.forEach(listener -> listener.onAppEvent(sender, e));
    }

    // 事件监听器接口定义
    @FunctionalInterface
    private interface ModuleDataLoadListener {
        void onModuleDataLoad(ModuleBaseEntity module);
    }

    @FunctionalInterface
    private interface ModuleDataChangeListener {
        void onModuleDataChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response);
    }

    @FunctionalInterface
    private interface ModuleStateChangeListener {
        void onModuleStateChange(ModuleBaseEntity module, SystemEnums.ActionType aType, BaseResponse response);
    }

    @FunctionalInterface
    private interface ModuleAuditStateChangeListener {
        void onModuleAuditStateChange(ModuleBaseEntity module, BillStateEn stateEn, BaseResponse response);
    }

    @FunctionalInterface
    private interface ModuleContextMenuListener {
        void onModuleContextMenu(SysPoPupMenuBtn btn, BaseResponse response);
    }

    @FunctionalInterface
    private interface FileUploadListener {
        void onFileUpload(FileUtil.PathInfo info, BaseResponse response);
    }

    @FunctionalInterface
    private interface AppListener {
        void onAppEvent(Object sender, EventArgs e);
    }
}