#pragma once

#include "base.hpp"

#ifdef QKMEANS_HAS_HNSWLIB
#include <hnswlib/hnswlib.h>
#endif

namespace qkmeans {
namespace anns {

#ifdef QKMEANS_HAS_HNSWLIB

/**
 * @brief HNSW-based approximate nearest neighbor index.
 *
 * Uses hnswlib's Hierarchical Navigable Small World graphs for
 * efficient approximate nearest neighbor search. HNSW provides
 * excellent query performance with logarithmic complexity.
 */
class HNSWIndex : public ANNSBase {
public:
    /**
     * @brief Construct HNSW index from config.
     */
    explicit HNSWIndex(const ANNSConfig& config);

    /**
     * @brief Construct HNSW index with explicit parameters.
     *
     * @param dim Dimensionality of vectors.
     * @param max_elements Maximum number of elements to store.
     * @param M Number of bi-directional links per node (default: 16).
     * @param ef_construction Size of dynamic list during construction (default: 200).
     * @param ef_search Size of dynamic list during search (default: 50).
     */
    HNSWIndex(size_t dim, size_t max_elements,
              size_t M = 16, size_t ef_construction = 200, size_t ef_search = 50);

    ~HNSWIndex() override = default;

    void insert(const double* point, size_t idx) override;
    QueryResult query(const double* point) const override;
    void batch_query(const double* points, size_t n,
                     size_t* indices_out, double* distances_out) const override;
    size_t size() const override;
    size_t dimension() const override { return dim_; }
    void clear() override;
    void reserve(size_t n) override;

private:
    size_t dim_;
    size_t max_elements_;
    size_t M_;
    size_t ef_construction_;
    size_t ef_search_;
    size_t num_points_ = 0;

    std::unique_ptr<hnswlib::L2Space> space_;
    std::unique_ptr<hnswlib::HierarchicalNSW<float>> index_;

    // Buffer for float conversion (hnswlib uses float)
    mutable std::vector<float> query_buffer_;
    std::vector<float> insert_buffer_;
};

#endif // QKMEANS_HAS_HNSWLIB

} // namespace anns
} // namespace qkmeans
