using MongoDB.Driver;
using System.Linq.Expressions;
namespace Core.Blueprint.Mongo
{
    /// 
    /// Interface for performing CRUD operations and queries on MongoDB collections.
    /// The  represents the type of documents in the collection,
    /// which must implement the  interface.
    /// 
    /// The type of document in the MongoDB collection, must implement .
    public interface ICollectionsRepository where TDocument : IDocument
    {
        /// 
        /// Retrieves all documents from the collection as an enumerable queryable result.
        /// 
        /// A  containing an  representing the collection's documents.
        ValueTask> AsQueryable();
        /// 
        /// Filters the documents in the collection by the provided filter expression.
        /// 
        /// An expression used to filter the documents based on the provided condition.
        /// A  representing the asynchronous operation, with a result of an  of filtered documents.
        Task> FilterBy(
            Expression> filterExpression);
        /// 
        /// Filters the documents in the collection by the provided filter expression and projects them to a different type.
        /// 
        /// The type to project the documents into.
        /// An expression used to filter the documents.
        /// An expression used to project the filtered documents into the  type.
        /// An  representing the projected documents.
        IEnumerable FilterBy(
            Expression> filterExpression,
            Expression> projectionExpression);
        /// 
        /// Filters documents in the collection based on the provided MongoDB filter definition.
        /// 
        /// A filter definition for MongoDB query.
        /// A task that represents the asynchronous operation. The task result contains a list of documents that match the filter.
        Task> FilterByMongoFilterAsync(FilterDefinition filterDefinition);
        /// 
        /// Finds a single document by the provided filter expression.
        /// 
        /// An expression used to filter the documents.
        /// The first matching  or null if no match is found.
        TDocument FindOne(Expression> filterExpression);
        /// 
        /// Asynchronously finds a single document by the provided filter expression.
        /// 
        /// An expression used to filter the documents.
        /// A  representing the asynchronous operation, with the matching  or null.
        Task FindOneAsync(Expression> filterExpression);
        /// 
        /// Finds a document by its identifier.
        /// 
        /// The identifier of the document.
        /// The document with the provided identifier or null if not found.
        TDocument FindById(string id);
        /// 
        /// Asynchronously finds a document by its identifier.
        /// 
        /// The identifier of the document.
        /// A  representing the asynchronous operation, with the matching  or null.
        Task FindByIdAsync(string id);
        /// 
        /// Inserts a single document into the collection.
        /// 
        /// The document to insert.
        void InsertOne(TDocument document);
        /// 
        /// Asynchronously inserts a single document into the collection.
        /// 
        /// The document to insert.
        /// A  representing the asynchronous operation.
        Task InsertOneAsync(TDocument document);
        /// 
        /// Inserts multiple documents into the collection.
        /// 
        /// The collection of documents to insert.
        void InsertMany(ICollection documents);
        /// 
        /// Asynchronously inserts multiple documents into the collection.
        /// 
        /// The collection of documents to insert.
        /// A  representing the asynchronous operation.
        Task InsertManyAsync(ICollection documents);
        /// 
        /// Replaces an existing document with a new one.
        /// 
        /// The document to replace the existing one.
        void ReplaceOne(TDocument document);
        /// 
        /// Asynchronously replaces an existing document with a new one.
        /// 
        /// The document to replace the existing one.
        /// A  representing the asynchronous operation.
        Task ReplaceOneAsync(TDocument document);
        /// 
        /// Deletes a single document by the provided filter expression.
        /// 
        /// An expression used to filter the documents to delete.
        void DeleteOne(Expression> filterExpression);
        /// 
        /// Asynchronously deletes a single document by the provided filter expression.
        /// 
        /// An expression used to filter the documents to delete.
        /// A  representing the asynchronous operation.
        Task DeleteOneAsync(Expression> filterExpression);
        /// 
        /// Deletes a single document by its identifier.
        /// 
        /// The identifier of the document to delete.
        void DeleteById(string id);
        /// 
        /// Asynchronously deletes a single document by its identifier.
        /// 
        /// The identifier of the document to delete.
        /// A  representing the asynchronous operation.
        Task DeleteByIdAsync(string id);
        /// 
        /// Deletes multiple documents that match the provided filter expression.
        /// 
        /// An expression used to filter the documents to delete.
        void DeleteMany(Expression> filterExpression);
        /// 
        /// Asynchronously deletes multiple documents that match the provided filter expression.
        /// 
        /// An expression used to filter the documents to delete.
        /// A  representing the asynchronous operation.
        Task DeleteManyAsync(Expression> filterExpression);
        /// 
        /// Executes an aggregation pipeline and returns the first document in the result asynchronously.
        /// 
        /// The type of the output document you expect from the pipeline.
        /// The aggregation pipeline definition to execute.
        /// The first document from the aggregation result, or null if none found.
        Task FindOnePipelineAsync(PipelineDefinition pipeline);
    }
}