use super::{
    builder::{QueryBuilder, StorageBuilder},
    EncryptionError, IndexTerm,
};

pub trait IndexerInit: Sized {
    type Args;
    type Error;

    fn try_init<A>(args: A) -> Result<Self, Self::Error>
    where
        Self::Args: TryFrom<A, Error = Self::Error>;
}

pub trait Indexes<'k, T>: Sized {
    // If this was serde, the error type would be whatever error is associated with the builder
    // We can do that so we can have different errors for Query vs Store
    fn index(
        &self,
        builder: StorageBuilder<'k, T>,
    ) -> Result<StorageBuilder<'k, T>, EncryptionError>;
}

/// Query operations for STE-vec indexed columns.
///
/// # Operations
///
/// - [`QueryOp::Default`]: For JSON containment queries (`@>`). Pass a JSON object/array.
/// - [`QueryOp::SteVecSelector`]: For path extraction. Pass a JSON path string like `"$.user.email"`.
/// - [`QueryOp::SteVecTerm`]: For scalar value comparison using CLWW ORE. Pass a string or number only.
///   Json values are not supported; use `Default` for JSON containment queries.
#[derive(Debug, Clone, Copy)]
pub enum QueryOp {
    /// For JSON containment queries. Accepts JSON objects/arrays.
    Default,
    /// For JSON path extraction. Accepts path strings like `"$.user.email"`.
    SteVecSelector,
    /// For scalar value comparison using CLWW ORE. Accepts strings or numbers only.
    SteVecTerm,
}

/// Trait for indexers to generate a term for a query.
/// Only one term can be generated per query and so it is returned directly.
pub trait IndexesForQuery<T, C>: Sized {
    // add op enum as arg here
    fn query_index(
        &self,
        builder: QueryBuilder<T, C>,
        op: QueryOp,
    ) -> Result<IndexTerm, EncryptionError>;
}
