#pragma once

// DragonX Wallet - HushChat crypto primitives.
//
// crypto_kx (X25519) session-key agreement + crypto_secretstream_xchacha20poly1305
// message encryption, byte-exact per the HushChat wire format so DragonX interoperates
// with SilentDragonXLite. See docs/_archive/contacts-chat-phase1-detail-2026-07-05.md
// (Appendix A.3/A.4). Pure crypto — no gating, no I/O; the feature gate lives at the
// service layer. NEVER logs plaintext, ciphertext, keys, or session material.

#include <array>
#include <cstddef>
#include <string>

namespace dragonx::chat {

// crypto_kx key sizes (== crypto_kx_PUBLICKEYBYTES / SECRETKEYBYTES == 32).
constexpr std::size_t kChatKeyBytes = 32;

using ChatPublicKey = std::array<unsigned char, kChatKeyBytes>;
using ChatSecretKey = std::array<unsigned char, kChatKeyBytes>;

struct ChatKeyPair {
    ChatPublicKey public_key{};
    ChatSecretKey secret_key{};
};

enum class ChatCryptoStatus {
    Ok,
    SodiumInitFailed,
    BadPeerKey,          // peer public-key hex missing / wrong length / not hex
    BadHeaderHex,        // secretstream header hex missing / wrong length / not hex
    BadCiphertextHex,    // ciphertext hex malformed
    CiphertextTooShort,  // ciphertext shorter than the auth tag
    SessionKeyFailed,    // crypto_kx_*_session_keys rejected the peer key
    EncryptFailed,
    DecryptFailed        // init_pull / pull / tag mismatch — the single neutral auth failure
};

const char* chatCryptoStatusName(ChatCryptoStatus status);

// Encrypt `plaintext` addressed to peer `peerPublicKeyHex` (64 lowercase hex chars).
// Sender takes the crypto_kx "server" role (server_tx), matching SDXL's send path.
// Outputs the secretstream header hex (the memo "e" field) and the ciphertext hex
// (the payload memo). Returns Ok on success.
ChatCryptoStatus encryptOutgoing(const ChatKeyPair& mine,
                                 const std::string& peerPublicKeyHex,
                                 const std::string& plaintext,
                                 std::string& outStreamHeaderHex,
                                 std::string& outCiphertextHex);

// Decrypt an incoming message addressed to us from peer `peerPublicKeyHex`.
// Receiver takes the crypto_kx "client" role (client_rx), matching SDXL's receive path.
// Requires the memo "e" (streamHeaderHex) and the payload ciphertext hex. Enforces the
// Poly1305 auth tag AND that the stream tag is TAG_FINAL. Returns Ok + fills outPlaintext.
ChatCryptoStatus decryptIncoming(const ChatKeyPair& mine,
                                 const std::string& peerPublicKeyHex,
                                 const std::string& streamHeaderHex,
                                 const std::string& ciphertextHex,
                                 std::string& outPlaintext);

// Zero both key arrays (call when discarding an identity's keys).
void wipeChatKeyPair(ChatKeyPair& keys);

} // namespace dragonx::chat
