namespace ZB.MOM.WW.CBDD.Core.Indexing;

/// <summary>
///     Types of indices supported
/// </summary>
public enum IndexType : byte
{
    /// <summary>B+Tree index for range queries and ordering</summary>
    BTree = 1,

    /// <summary>Hash index for exact match lookups</summary>
    Hash = 2,

    /// <summary>Unique index constraint</summary>
    Unique = 3,

    /// <summary>Vector index (HNSW) for similarity search</summary>
    Vector = 4,

    /// <summary>Geospatial index (R-Tree) for spatial queries</summary>
    Spatial = 5
}

/// <summary>
///     Distance metrics for vector search
/// </summary>
public enum VectorMetric : byte
{
    /// <summary>Cosine Similarity (Standard for embeddings)</summary>
    Cosine = 1,

    /// <summary>Euclidean Distance (L2)</summary>
    L2 = 2,

    /// <summary>Dot Product</summary>
    DotProduct = 3
}

/// <summary>
///     Index options and configuration.
///     Implemented as readonly struct for efficiency.
/// </summary>
public readonly struct IndexOptions
{
    /// <summary>
    ///     Gets the configured index type.
    /// </summary>
    public IndexType Type { get; init; }

    /// <summary>
    ///     Gets a value indicating whether the index enforces uniqueness.
    /// </summary>
    public bool Unique { get; init; }

    /// <summary>
    ///     Gets the indexed field names.
    /// </summary>
    public string[] Fields { get; init; }

    // Vector search options
    /// <summary>
    ///     Gets the vector dimensionality for vector indexes.
    /// </summary>
    public int Dimensions { get; init; }

    /// <summary>
    ///     Gets the distance metric used for vector similarity.
    /// </summary>
    public VectorMetric Metric { get; init; }

    /// <summary>
    ///     Gets the minimum number of graph connections per node.
    /// </summary>
    public int M { get; init; } // Min number of connections per node

    /// <summary>
    ///     Gets the size of the dynamic candidate list during index construction.
    /// </summary>
    public int EfConstruction { get; init; } // Size of dynamic candidate list for construction

    /// <summary>
    ///     Creates non-unique B+Tree index options.
    /// </summary>
    /// <param name="fields">The indexed field names.</param>
    /// <returns>The configured index options.</returns>
    public static IndexOptions CreateBTree(params string[] fields)
    {
        return new IndexOptions
        {
            Type = IndexType.BTree,
            Unique = false,
            Fields = fields
        };
    }

    /// <summary>
    ///     Creates unique B+Tree index options.
    /// </summary>
    /// <param name="fields">The indexed field names.</param>
    /// <returns>The configured index options.</returns>
    public static IndexOptions CreateUnique(params string[] fields)
    {
        return new IndexOptions
        {
            Type = IndexType.BTree,
            Unique = true,
            Fields = fields
        };
    }

    /// <summary>
    ///     Creates hash index options.
    /// </summary>
    /// <param name="fields">The indexed field names.</param>
    /// <returns>The configured index options.</returns>
    public static IndexOptions CreateHash(params string[] fields)
    {
        return new IndexOptions
        {
            Type = IndexType.Hash,
            Unique = false,
            Fields = fields
        };
    }

    /// <summary>
    ///     Creates vector index options.
    /// </summary>
    /// <param name="dimensions">The vector dimensionality.</param>
    /// <param name="metric">The similarity metric.</param>
    /// <param name="m">The minimum number of graph connections per node.</param>
    /// <param name="ef">The candidate list size used during index construction.</param>
    /// <param name="fields">The indexed field names.</param>
    /// <returns>The configured index options.</returns>
    public static IndexOptions CreateVector(int dimensions, VectorMetric metric = VectorMetric.Cosine, int m = 16,
        int ef = 200, params string[] fields)
    {
        return new IndexOptions
        {
            Type = IndexType.Vector,
            Unique = false,
            Fields = fields,
            Dimensions = dimensions,
            Metric = metric,
            M = m,
            EfConstruction = ef
        };
    }

    /// <summary>
    ///     Creates spatial index options.
    /// </summary>
    /// <param name="fields">The indexed field names.</param>
    /// <returns>The configured index options.</returns>
    public static IndexOptions CreateSpatial(params string[] fields)
    {
        return new IndexOptions
        {
            Type = IndexType.Spatial,
            Unique = false,
            Fields = fields
        };
    }
}