#pragma once

// DragonX Wallet - HushChat identity derivation.
//
// The DragonX-native chat identity is an X25519 (crypto_kx) keypair derived from a stable
// per-wallet secret via a domain-separated keyed BLAKE2b KDF. This deliberately does NOT
// use SDXL's UTF-8-hex-seed quirk (that quirk is only for the Phase-4 "import an existing
// SDXL identity" path). Interop is unaffected: identity derivation is local — peers only
// exchange public keys. See docs/_archive/contacts-chat-tab-plan-2026-07-05.md §5.6.

#include "chat_crypto.h"     // ChatKeyPair
#include "chat_protocol.h"   // hushChatFeatureEnabledAtBuild()

#include <cstddef>
#include <string>

namespace dragonx::chat {

// Domain-separation label — used as the BLAKE2b key so a different app/version cannot
// derive the same identity from the same wallet secret. A char[] (not const char*) so its
// length is a compile-time constant for the KEYBYTES-bounds static_assert.
inline constexpr char kChatIdentityKdfContext[] = "DragonX-HushChat-Identity-v1";
inline constexpr std::size_t kChatIdentityKdfContextLen = sizeof(kChatIdentityKdfContext) - 1;

enum class ChatIdentityStatus {
    Ready,
    FeatureDisabled,     // DRAGONX_ENABLE_CHAT off (or caller passed featureEnabled=false)
    SecretUnavailable,   // no stable secret (wallet locked / not open / empty)
    DerivationFailed     // libsodium init or KDF/keypair failure
};

const char* chatIdentityStatusName(ChatIdentityStatus status);

struct ChatIdentityResult {
    ChatIdentityStatus status = ChatIdentityStatus::FeatureDisabled;
    std::string public_key_hex;                 // 64 lowercase hex chars when Ready
    const char* error_name = "FeatureDisabled"; // == chatIdentityStatusName(status)
};

// Pure, no-I/O derivation: hashes `stableSecret` (variable-length: a mnemonic on lite, a
// spending key on full-node) with the KDF context as the BLAKE2b key into a clean 32-byte
// crypto_kx seed, then crypto_kx_seed_keypair() into `outKeys`. Deterministic for a given
// secret. On any non-Ready result `outKeys` is left wiped. featureEnabled defaults to the
// build predicate but tests pass true to exercise the crypto in an OFF build.
//
// OWNERSHIP: `stableSecret` is BORROWED (const&) and is NOT wiped here — the caller owns it
// and MUST sodium_memzero its backing buffer after this returns. The per-variant provider
// that fetches the wallet secret (mnemonic / spending key) should hold it in a wipeable
// buffer, not a plain std::string literal, in production.
ChatIdentityResult deriveChatIdentityFromSecret(const std::string& stableSecret,
                                                ChatKeyPair& outKeys,
                                                bool featureEnabled = hushChatFeatureEnabledAtBuild());

// 64-char lowercase hex of the public key.
std::string chatIdentityPublicKeyHex(const ChatKeyPair& keys);

} // namespace dragonx::chat
