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

#pragma once

#include <string>
#include <vector>
#include <utility>

namespace dragonx {
namespace rpc {

/**
 * @brief Connection configuration
 */
enum class AuthSource {
    Missing,
    ConfigFile,
    Cookie
};

struct ConnectionConfig {
    std::string host = "127.0.0.1";
    std::string port = "21769";
    std::string rpcuser;
    std::string rpcpassword;
    std::string hush_dir;
    std::string proxy;  // SOCKS5 proxy for Tor
    bool use_embedded = true;
    bool use_tls = false;
    bool allow_plaintext_remote = false;  // rpcallowplaintext=1 — opt in to plaintext creds to a remote host
    AuthSource auth_source = AuthSource::Missing;
    // Non-empty when autoDetectConfig() could not create the data directory; callers
    // should surface it and abort the connect rather than proceeding blindly.
    std::string dir_error;
};

/**
 * @brief Manages connection to dragonxd
 * 
 * Handles auto-detection of DRAGONX.conf, starting embedded daemon,
 * and connection lifecycle.
 */
class Connection {
public:
    Connection();
    ~Connection();

    /**
     * @brief Auto-detect and load connection config
     * @return Config from DRAGONX.conf or defaults
     */
    static ConnectionConfig autoDetectConfig();

    /**
     * @brief Get the default DRAGONX.conf location
     */
    static std::string getDefaultConfPath();

    /**
     * @brief Get the default DragonX data directory
     */
    static std::string getDefaultDataDir();

    /**
     * @brief Parse a DRAGONX.conf file
     * @param path Path to conf file
     * @return Parsed configuration
     */
    static ConnectionConfig parseConfFile(const std::string& path);

    /**
     * @brief Check if Sapling params exist
     */
    static bool verifySaplingParams();

    // Verify the Sapling params in `dir` against a { filename, expected-sha256-hex } list.
    // Exposed with an injectable dir + digest list so the integrity + marker-cache logic is
    // unit-testable without the real ~48MB params; verifySaplingParams() calls it with the
    // pinned production digests and getSaplingParamsDir().
    static bool verifySaplingParamsIn(
        const std::string& dir,
        const std::vector<std::pair<std::string, std::string>>& digests);

    /**
     * @brief Get the Sapling params directory
     */
    static std::string getSaplingParamsDir();

    /**
     * @brief Create a default DRAGONX.conf file
     * @param path Path to create the file
     * @return true if created successfully
     */
    static bool createDefaultConfig(const std::string& path);

    /**
     * @brief Ensure exportdir is set in DRAGONX.conf
     * @param confPath Path to the conf file
     * @return true if exportdir exists or was added
     */
    static bool ensureExportDir(const std::string& confPath);

    /**
     * @brief Ensure wallet encryption flags are set in DRAGONX.conf
     * @param confPath Path to the conf file
     * @return true if flags exist or were added
     */
    static bool ensureEncryptionEnabled(const std::string& confPath);

    /**
     * @brief Try to read .cookie auth file from the data directory
     * @param dataDir Path to the daemon data directory
     * @param user Output: cookie username (__cookie__)
     * @param password Output: cookie password
     * @return true if cookie file was read successfully
     */
    static bool readAuthCookie(const std::string& dataDir, std::string& user, std::string& password);

    /**
     * @brief Build a cookie-auth retry config from a failed config-auth attempt
     */
    static bool buildCookieAuthConfig(const ConnectionConfig& base, ConnectionConfig& cookieConfig);

    /**
     * @brief Whether a host is local enough for plaintext HTTP RPC
     */
    static bool isLocalHost(const std::string& host);

    /**
     * @brief Whether this config would send RPC credentials over plaintext to a remote host
     */
    static bool usesPlaintextRemote(const ConnectionConfig& config);

    // Whether plaintext credentials to a remote host are explicitly allowed (opt-in via the
    // DRAGONX.conf rpcallowplaintext key). Off by default: usesPlaintextRemote() && !this
    // means the connect is refused.
    static bool allowsPlaintextRemote(const ConnectionConfig& config);

    static const char* authSourceName(AuthSource source);

private:
};

} // namespace rpc
} // namespace dragonx
