/*
 * crypto/tofu_store.h — Trust-On-First-Use pin storage.
 *
 * File format: one "host:port <hex-fingerprint>\n" line per entry.
 * Used by clients to remember server fingerprints across reconnects.
 */
#ifndef VOICECAT_CRYPTO_TOFU_STORE_H
#define VOICECAT_CRYPTO_TOFU_STORE_H

#ifdef VOICECAT_HAS_NET

#include <array>
#include <filesystem>
#include <mutex>
#include <string>
#include <unordered_map>

namespace voicecat::crypto {

enum class TofuResult {
    FirstConnect,  // no pin on file; pin has been stored
    Matched,       // pin matches stored value
    Mismatch,      // stored pin does not match — possible MITM or server key rotation
};

class TofuStore {
   public:
    explicit TofuStore(std::filesystem::path path);

    // Check the fingerprint for host:port. Stores on first connect.
    // Thread-safe (single-writer lock).
    // NOTE: kept for compatibility; the M4 gated-confirmation flow (vc_client) uses peek()
    // + pin() instead, since check_and_pin's unconditional first-connect write is wrong for a
    // flow where the application must approve the fingerprint before it's trusted/persisted.
    TofuResult check_and_pin(const std::string& host, uint16_t port,
                              const std::array<uint8_t, 32>& fingerprint);

    // Read-only — classifies the fingerprint against any existing pin WITHOUT writing to disk.
    // Use this before the application has had a chance to approve a first-connect/mismatch.
    TofuResult peek(const std::string& host, uint16_t port,
                     const std::array<uint8_t, 32>& fingerprint) const;

    // Persist the pin for host:port. Call only after the caller has accepted a FIRST_CONNECT
    // or MISMATCH classification from peek() — accepting a MATCHED result needs no call here.
    void pin(const std::string& host, uint16_t port, const std::array<uint8_t, 32>& fingerprint);

    // Remove the pin for host:port (e.g. after user explicitly acknowledges a key change).
    void remove(const std::string& host, uint16_t port);

   private:
    static std::string make_key(const std::string& host, uint16_t port);
    static std::string fp_to_hex(const std::array<uint8_t, 32>& fp);
    static std::array<uint8_t, 32> hex_to_fp(const std::string& hex);

    void load();
    void save() const;

    std::filesystem::path path_;
    mutable std::mutex    mu_;
    std::unordered_map<std::string, std::array<uint8_t, 32>> pins_;
};

}  // namespace voicecat::crypto

#endif  // VOICECAT_HAS_NET
#endif  // VOICECAT_CRYPTO_TOFU_STORE_H
