#pragma once

// DragonX Wallet - HushChat persistent message store (Phase 2).
//
// Sqlite-backed, encrypted at rest with a SEED-DERIVED key (no wallet passphrase). Every record —
// message bodies, peer z-addresses, threading (conversation id), and timestamps — is AEAD-encrypted
// under a key derived from the wallet's own seed secret (the same secret used for the chat
// identity), and even the per-message dedup key is a KEYED hash of the txid — so the database
// reveals nothing about your conversations to disk-level access without the seed. Rows are
// partitioned by a seed-derived wallet tag so one file can hold several wallets, each readable only
// with its own seed. Not thread-safe — drive from the main thread. Mirrors the lifecycle of
// data::TransactionHistoryCache.

#include "chat_message.h"

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

struct sqlite3;

namespace dragonx::chat {

class ChatDatabase {
public:
    ChatDatabase();
    explicit ChatDatabase(std::string databasePath);
    ~ChatDatabase();

    ChatDatabase(const ChatDatabase&) = delete;
    ChatDatabase& operator=(const ChatDatabase&) = delete;

    static std::string defaultDatabasePath();

    // Derive the storage key + wallet tag from the wallet's seed secret and open the DB. The caller
    // still owns and must wipe `secret`. Returns false on sodium/db failure (DB then stays locked).
    bool unlockWithSecret(const std::string& secret);
    void lock();  // wipe the key material (DB handle stays open); load()/append() then no-op
    bool hasKey() const { return key_ready_; }

    // Persist one message (INSERT OR IGNORE, deduped by a keyed hash of txid+payload_position).
    // Returns true if newly inserted; false on duplicate or while locked.
    bool append(const ChatMessage& message);

    // Decrypt and return every stored message for the unlocked wallet, in insertion order. Empty
    // while locked or if none. Rows that fail to decrypt/parse are skipped.
    std::vector<ChatMessage> load();

    void clearWallet();  // delete the unlocked wallet's rows

private:
    bool ensureOpen();
    bool exec(const char* sql);
    bool createSchema();
    std::string dedupHash(const std::string& txid, std::size_t position) const;
    std::string serialize(const ChatMessage& message) const;
    bool deserialize(const std::string& json, ChatMessage& out) const;
    bool encrypt(const std::string& plain,
                 std::vector<unsigned char>& nonce,
                 std::vector<unsigned char>& cipher) const;
    bool decrypt(const std::vector<unsigned char>& nonce,
                 const std::vector<unsigned char>& cipher,
                 std::string& plain) const;
    void close();

    sqlite3* db_ = nullptr;
    std::string database_path_;
    std::array<unsigned char, 32> key_{};  // AEAD storage key (seed-derived)
    std::string wallet_tag_;               // seed-derived row partition (a keyed hash, hex)
    bool key_ready_ = false;
};

} // namespace dragonx::chat
