/**
 * Synor Privacy SDK for C++
 * Confidential transactions, ring signatures, stealth addresses, and cryptographic commitments.
 */

#ifndef SYNOR_PRIVACY_HPP
#define SYNOR_PRIVACY_HPP

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

namespace synor::privacy {

inline constexpr const char* VERSION = "0.1.0";

// ==================== Exceptions ====================

class PrivacyException : public std::runtime_error {
public:
    PrivacyException(const std::string& message,
                     std::optional<int> status_code = std::nullopt,
                     std::optional<std::string> code = std::nullopt)
        : std::runtime_error(message), status_code_(status_code), code_(code) {}

    std::optional<int> status_code() const { return status_code_; }
    std::optional<std::string> code() const { return code_; }

private:
    std::optional<int> status_code_;
    std::optional<std::string> code_;
};

// ==================== Configuration ====================

struct PrivacyConfig {
    std::string api_key;
    std::string endpoint = "https://privacy.synor.io";
    int timeout_ms = 30000;
    int retries = 3;
};

// ==================== Confidential Transactions ====================

struct ConfidentialTxInput {
    std::string commitment;
    std::string blinding_factor;
    std::string value;
    std::optional<std::string> key_image;
};

struct ConfidentialTxOutput {
    std::string commitment;
    std::string blinding_factor;
    std::string value;
    std::string recipient_public_key;
    std::optional<std::string> range_proof;
};

struct ConfidentialTransaction {
    std::string id;
    std::vector<ConfidentialTxInput> inputs;
    std::vector<ConfidentialTxOutput> outputs;
    std::string fee;
    std::string excess;
    std::string excess_sig;
    std::optional<std::string> kernel_offset;
};

// ==================== Commitments ====================

struct Commitment {
    std::string commitment;
    std::string blinding_factor;
};

struct RangeProof {
    std::string proof;
    std::string commitment;
    int64_t min_value;
    int64_t max_value;
};

// ==================== Ring Signatures ====================

struct RingSignature {
    std::string c0;
    std::vector<std::string> s;
    std::string key_image;
    std::vector<std::string> ring;
};

// ==================== Stealth Addresses ====================

struct StealthKeyPair {
    std::string spend_public_key;
    std::string spend_private_key;
    std::string view_public_key;
    std::string view_private_key;
};

struct StealthAddress {
    std::string address;
    std::string ephemeral_public_key;
    std::optional<std::string> tx_public_key;
};

struct StealthOutput {
    std::string tx_hash;
    int output_index;
    std::string stealth_address;
    std::string amount;
    int64_t block_height;
};

// ==================== Client ====================

class PrivacyClient {
public:
    explicit PrivacyClient(const PrivacyConfig& config);
    ~PrivacyClient();

    // Non-copyable
    PrivacyClient(const PrivacyClient&) = delete;
    PrivacyClient& operator=(const PrivacyClient&) = delete;

    // Movable
    PrivacyClient(PrivacyClient&&) noexcept;
    PrivacyClient& operator=(PrivacyClient&&) noexcept;

    // Confidential Transactions
    std::future<ConfidentialTransaction> create_confidential_tx(
        const std::vector<ConfidentialTxInput>& inputs,
        const std::vector<ConfidentialTxOutput>& outputs
    );

    std::future<bool> verify_confidential_tx(const ConfidentialTransaction& tx);

    std::future<Commitment> create_commitment(
        const std::string& value,
        const std::string& blinding_factor
    );

    std::future<bool> verify_commitment(
        const std::string& commitment,
        const std::string& value,
        const std::string& blinding_factor
    );

    std::future<RangeProof> create_range_proof(
        const std::string& value,
        const std::string& blinding_factor,
        int64_t min_value,
        int64_t max_value
    );

    std::future<bool> verify_range_proof(const RangeProof& proof);

    // Ring Signatures
    std::future<RingSignature> create_ring_signature(
        const std::string& message,
        const std::vector<std::string>& ring,
        int signer_index,
        const std::string& private_key
    );

    std::future<bool> verify_ring_signature(
        const RingSignature& signature,
        const std::string& message
    );

    std::future<std::vector<std::string>> generate_decoys(
        int count,
        const std::optional<std::string>& exclude_key = std::nullopt
    );

    std::future<bool> check_key_image(const std::string& key_image);

    // Stealth Addresses
    std::future<StealthKeyPair> generate_stealth_keypair();

    std::future<StealthAddress> derive_stealth_address(
        const std::string& spend_public_key,
        const std::string& view_public_key
    );

    std::future<std::string> recover_stealth_private_key(
        const std::string& stealth_address,
        const std::string& view_private_key,
        const std::string& spend_private_key
    );

    std::future<std::vector<StealthOutput>> scan_outputs(
        const std::string& view_private_key,
        const std::string& spend_public_key,
        int64_t from_block,
        std::optional<int64_t> to_block = std::nullopt
    );

    // Blinding
    std::future<std::string> generate_blinding_factor();

    std::future<std::string> blind_value(
        const std::string& value,
        const std::string& blinding_factor
    );

    std::future<std::string> unblind_value(
        const std::string& blinded_value,
        const std::string& blinding_factor
    );

    // Lifecycle
    std::future<bool> health_check();
    void close();
    bool is_closed() const;

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

} // namespace synor::privacy

#endif // SYNOR_PRIVACY_HPP
