#pragma once
#include <stdexcept>
#include "spdlog/spdlog.h"

#ifdef _WIN32
#include <Windows.h>
#else
#include <dlfcn.h>
#endif

class CORE_API dynamic_library {
public:
    dynamic_library() {

    }

    explicit dynamic_library(const std::string& library_path) {
#ifdef _WIN32
        hModule = LoadLibraryA(library_path.c_str());
#else
        handle = dlopen(library_path.c_str(), RTLD_LAZY);
#endif
        if (!get_handle()) {
            spdlog::error("Failed to load library: {}", library_path);
            throw std::runtime_error("Failed to load library");
        }
        spdlog::info("Load library: {}", library_path);
    }

    ~dynamic_library() {
#ifdef _WIN32
        if (hModule) FreeLibrary(hModule);
#else
        if (handle) dlclose(handle);
#endif
    }

    [[nodiscard]] void* get_function(const char* functionName) const {
#ifdef _WIN32
        return (void*)GetProcAddress(hModule, functionName);
#else
        dlerror(); // 清除之前的错误
        void* function = dlsym(handle, functionName);
        // 添加错误检查
        return function;
#endif
    }

    [[nodiscard]] void* get_handle() const {
#ifdef _WIN32
        return hModule;
#else
        return handle;
#endif
    }
private:
#ifdef _WIN32
    HMODULE hModule = nullptr;
#else
    void* handle = nullptr;
#endif
};