// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

#include <string>

namespace dragonx {
namespace wallet {

struct LiteBridgeStringResult {
    bool ok = false;
    std::string value;
    std::string error;
};

struct LiteClientBridgeApi {
    using WalletExistsFn = bool (*)(const char* chainName);
    using InitializeNewFn = char* (*)(bool dangerous, const char* server);
    using InitializeNewFromPhraseFn = char* (*)(bool dangerous,
                                                const char* server,
                                                const char* seed,
                                                unsigned long long birthday,
                                                unsigned long long account,
                                                bool overwrite);
    using InitializeExistingFn = char* (*)(bool dangerous, const char* server);
    using ExecuteFn = char* (*)(const char* command, const char* args);
    using FreeStringFn = void (*)(char* value);
    using CheckServerOnlineFn = bool (*)(const char* server);
    using ShutdownFn = void (*)();

    WalletExistsFn walletExists = nullptr;
    InitializeNewFn initializeNew = nullptr;
    InitializeNewFromPhraseFn initializeNewFromPhrase = nullptr;
    InitializeExistingFn initializeExisting = nullptr;
    ExecuteFn execute = nullptr;
    FreeStringFn freeString = nullptr;
    CheckServerOnlineFn checkServerOnline = nullptr;
    ShutdownFn shutdown = nullptr;
};

class LiteClientBridge {
public:
    static LiteClientBridge unavailable(std::string reason);
    static LiteClientBridge fromApi(LiteClientBridgeApi api);
    static LiteClientBridge linkedSdxl();

    LiteClientBridge(const LiteClientBridge&) = delete;
    LiteClientBridge& operator=(const LiteClientBridge&) = delete;
    LiteClientBridge(LiteClientBridge&& other) noexcept;
    LiteClientBridge& operator=(LiteClientBridge&& other) noexcept;
    ~LiteClientBridge();

    bool available() const;
    const std::string& unavailableReason() const { return unavailableReason_; }

    bool walletExists(const std::string& chainName) const;
    bool checkServerOnline(const std::string& server) const;

    LiteBridgeStringResult initializeNew(bool dangerous, const std::string& server);
    LiteBridgeStringResult initializeNewFromPhrase(bool dangerous,
                                                   const std::string& server,
                                                   const std::string& seed,
                                                   unsigned long long birthday,
                                                   unsigned long long account,
                                                   bool overwrite);
    LiteBridgeStringResult initializeExisting(bool dangerous, const std::string& server);
    LiteBridgeStringResult execute(const std::string& command, const std::string& args);
    void shutdown();

private:
    LiteClientBridge(LiteClientBridgeApi api, std::string unavailableReason);

    LiteBridgeStringResult unavailableResult() const;
    LiteBridgeStringResult takeOwnedString(char* rawValue) const;

    LiteClientBridgeApi api_;
    std::string unavailableReason_;
    bool shutdownCalled_ = false;
};

} // namespace wallet
} // namespace dragonx