/**
 * @file wallet.hpp
 * @brief Synor Wallet SDK for C++
 *
 * Modern C++17 SDK for key management, transaction signing, and balance queries.
 *
 * @example
 * ```cpp
 * #include <synor/wallet.hpp>
 *
 * int main() {
 *     synor::wallet::Config config{
 *         .api_key = "your-api-key",
 *         .endpoint = "https://wallet.synor.io/v1",
 *         .network = synor::Network::Mainnet
 *     };
 *
 *     synor::wallet::Client client(config);
 *
 *     // Create wallet
 *     auto result = client.create_wallet(synor::WalletType::Standard);
 *     std::cout << "Wallet ID: " << result.wallet.id << "\n";
 *     std::cout << "Mnemonic: " << result.mnemonic.value_or("N/A") << "\n";
 *
 *     // Get balance
 *     auto balance = client.get_balance(result.wallet.addresses[0].address);
 *     std::cout << "Balance: " << balance.total << "\n";
 *
 *     return 0;
 * }
 * ```
 */

#pragma once

#include <string>
#include <vector>
#include <optional>
#include <future>
#include <memory>
#include <cstdint>
#include <stdexcept>

namespace synor {

// Forward declarations
namespace wallet { class Client; }

/// Network environment
enum class Network {
    Mainnet,
    Testnet,
    Devnet
};

/// Wallet type
enum class WalletType {
    Standard,
    Multisig,
    Hardware,
    Stealth
};

/// Transaction priority
enum class Priority {
    Low,
    Medium,
    High
};

/// SDK exception
class SynorException : public std::runtime_error {
public:
    explicit SynorException(const std::string& message, int status_code = 0)
        : std::runtime_error(message), status_code_(status_code) {}

    int status_code() const noexcept { return status_code_; }

private:
    int status_code_;
};

namespace wallet {

/// Wallet configuration
struct Config {
    std::string api_key;
    std::string endpoint = "https://wallet.synor.io/v1";
    Network network = Network::Mainnet;
    uint32_t timeout_ms = 30000;
    uint32_t retries = 3;
    bool debug = false;
};

/// Wallet address
struct Address {
    std::string address;
    int32_t index;
    bool is_change = false;
};

/// Wallet information
struct Wallet {
    std::string id;
    WalletType type;
    Network network;
    std::vector<Address> addresses;
    std::string created_at;
};

/// Stealth address for privacy transactions
struct StealthAddress {
    std::string spend_public_key;
    std::string view_public_key;
    std::string one_time_address;
};

/// Result of wallet creation
struct CreateWalletResult {
    Wallet wallet;
    std::optional<std::string> mnemonic;
};

/// Transaction input (UTXO reference)
struct TransactionInput {
    std::string txid;
    int32_t vout;
    int64_t amount;
};

/// Transaction output
struct TransactionOutput {
    std::string address;
    int64_t amount;
};

/// Transaction for signing
struct Transaction {
    std::vector<TransactionInput> inputs;
    std::vector<TransactionOutput> outputs;
    std::optional<int64_t> fee;
    Priority priority = Priority::Medium;
};

/// Signed transaction
struct SignedTransaction {
    std::string txid;
    std::string hex;
    int32_t size;
    int64_t fee;
};

/// Cryptographic signature
struct Signature {
    std::string signature;
    std::string address;
    std::optional<int32_t> recovery_id;
};

/// Unspent transaction output
struct UTXO {
    std::string txid;
    int32_t vout;
    int64_t amount;
    std::string address;
    int32_t confirmations;
    std::optional<std::string> script_pubkey;
};

/// Wallet balance
struct Balance {
    int64_t confirmed;
    int64_t unconfirmed;
    int64_t total;
};

/// Wallet client
class Client {
public:
    explicit Client(const Config& config);
    ~Client();

    // Disable copy
    Client(const Client&) = delete;
    Client& operator=(const Client&) = delete;

    // Enable move
    Client(Client&&) noexcept;
    Client& operator=(Client&&) noexcept;

    /// Create a new wallet
    CreateWalletResult create_wallet(WalletType type = WalletType::Standard);

    /// Create a new wallet asynchronously
    std::future<CreateWalletResult> create_wallet_async(WalletType type = WalletType::Standard);

    /// Import a wallet from mnemonic
    Wallet import_wallet(const std::string& mnemonic,
                         const std::optional<std::string>& passphrase = std::nullopt);

    /// Get a wallet by ID
    Wallet get_wallet(const std::string& wallet_id);

    /// Generate a new address
    Address generate_address(const std::string& wallet_id, bool is_change = false);

    /// Get stealth address
    StealthAddress get_stealth_address(const std::string& wallet_id);

    /// Sign a transaction
    SignedTransaction sign_transaction(const std::string& wallet_id,
                                        const Transaction& transaction);

    /// Sign a message
    Signature sign_message(const std::string& wallet_id,
                           const std::string& message,
                           int32_t address_index = 0);

    /// Verify a message signature
    bool verify_message(const std::string& message,
                        const std::string& signature,
                        const std::string& address);

    /// Get balance for an address
    Balance get_balance(const std::string& address);

    /// Get balance asynchronously
    std::future<Balance> get_balance_async(const std::string& address);

    /// Get UTXOs for an address
    std::vector<UTXO> get_utxos(const std::string& address, int32_t min_confirmations = 1);

    /// Estimate transaction fee
    int64_t estimate_fee(Priority priority = Priority::Medium);

private:
    class Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace wallet
} // namespace synor
