#pragma once

#include <cstddef>
#include <string>
#include <vector>

#ifndef DRAGONX_ENABLE_CHAT
#define DRAGONX_ENABLE_CHAT 0
#endif

namespace dragonx::chat {

enum class HushChatHeaderType {
    Message,
    ContactRequest
};

struct HushChatHeader {
    int header_number = 0;
    int version = 0;
    std::string reply_zaddr;
    std::string conversation_id;
    HushChatHeaderType type = HushChatHeaderType::Message;
    std::string secretstream_header_hex;
    std::string public_key_hex;
    // Optional sender-stamped compose time (header "ts", Unix seconds). 0 = absent (older sender) → the
    // receiver falls back to the tx/receive time. Lets both sides show the SAME (send) time.
    std::int64_t sent_at = 0;
};

struct HushChatHeaderParseResult {
    bool ok = false;
    HushChatHeader header;
    std::string error;
};

struct HushChatMemoOutput {
    std::size_t position = 0;
    std::string memo;
};

struct HushChatMemoPair {
    HushChatHeader header;
    std::size_t header_position = 0;
    std::size_t payload_position = 0;
    std::string payload_memo;
};

enum class HushChatMemoGroupingIssue {
    InvalidHeader,
    MissingPayload,
    DuplicateHeader,
    OversizedMemo
};

struct HushChatMemoGroupingIssueInfo {
    HushChatMemoGroupingIssue issue = HushChatMemoGroupingIssue::InvalidHeader;
    std::size_t position = 0;
    std::string detail;
};

struct HushChatMemoGroupingResult {
    std::vector<HushChatMemoPair> pairs;
    std::vector<HushChatMemoGroupingIssueInfo> issues;
    std::size_t ignored_memo_count = 0;
};

struct HushChatTransactionInput {
    std::string txid;
    std::vector<HushChatMemoOutput> outputs;
};

struct HushChatTransactionMetadata {
    std::string txid;
    HushChatHeaderType type = HushChatHeaderType::Message;
    std::string conversation_id;
    std::string reply_zaddr;
    std::size_t header_position = 0;
    std::size_t payload_position = 0;
    std::size_t payload_size = 0;
    // Decrypt inputs carried through from the paired header + payload memos so the chat
    // service can actually decrypt (a Message) or read the request (a ContactRequest).
    std::string sender_public_key_hex;   // header "p": peer crypto_kx public key (hex)
    std::string secretstream_header_hex; // header "e": secretstream header (hex; empty for ContactRequest)
    std::string payload_memo;            // ciphertext hex (Message) or plaintext request text (ContactRequest)
    std::int64_t sent_at = 0;            // header "ts": sender compose time (Unix s); 0 = absent → use tx time
};

struct HushChatTransactionExtractionResult {
    bool feature_enabled = false;
    std::vector<HushChatTransactionMetadata> metadata;
    std::vector<HushChatMemoGroupingIssueInfo> issues;
    std::size_t ignored_memo_count = 0;
};

constexpr int kHushChatSupportedVersion = 0;
constexpr std::size_t kHushChatMemoByteLimit = 512;
constexpr std::size_t kHushChatPublicKeyHexLength = 64;
constexpr std::size_t kHushChatSecretstreamHeaderHexLength = 48;

constexpr bool hushChatFeatureEnabledAtBuild()
{
    return DRAGONX_ENABLE_CHAT != 0;
}

HushChatHeaderParseResult parseHushChatHeaderMemo(const std::string& memo);
HushChatMemoGroupingResult groupHushChatMemoOutputs(const std::vector<HushChatMemoOutput>& outputs);
HushChatTransactionExtractionResult extractHushChatTransactionMetadata(
    const HushChatTransactionInput& transaction,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
const char* hushChatHeaderTypeName(HushChatHeaderType type);
const char* hushChatMemoGroupingIssueName(HushChatMemoGroupingIssue issue);

} // namespace dragonx::chat
