using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.Masters;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Application.Repositories.Interfaces;

public interface IMasterListRepository<T> : IMongoRepository<T> where T : MasterList
{
    /// <summary>
    /// Deletes the entity identified by the specified identifier.
    /// </summary>
    /// <param name="id">The identifier of the entity to delete.</param>
    Task Delete(ObjectId id);
    /// <summary>
    /// Asynchronously updates the specified collection of items.
    /// </summary>
    /// <param name="list">The collection of items to update.</param>
    Task Update(T list);
    /// <summary>
    /// Asynchronously retrieves an entity identified by the specified <paramref name="id"/>, optionally resolving localized content using the given <paramref name="locale"/>. Returns <c>null</c> when no matching entity is found.
    /// </summary>
    /// <param name="id">The unique identifier of the entity to look up.</param>
    /// <param name="locale">The optional locale used to resolve localized fields of the retrieved entity.</param>
    /// <returns>A task that yields the matching entity, or <c>null</c> if the entity is not found.</returns>
    Task<T?> FindById(ObjectId id, LocaleEnum? locale);
    /// <summary>
    /// Asynchronously retrieves an entity of type <typeparamref name="T"/> by its unique identifier.
    /// Returns <c>null</c> when no matching entity is found.
    /// </summary>
    /// <param name="id">The unique identifier of the entity to locate.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the entity of type <typeparamref name="T"/> if found, or <c>null</c> otherwise.</returns>
    Task<T?> FindById(ObjectId id);
    /// <summary>
    /// Asynchronously retrieves an <see cref="OptionList"/> item identified by the specified master and option identifiers for the given locale.
    /// Returns <c>null</c> when no matching option item is found for the provided identifiers and locale.
    /// </summary>
    /// <param name="masterId">The master identifier used to scope the lookup of the option item.</param>
    /// <param name="optionId">The identifier of the specific option item to retrieve within the master scope.</param>
    /// <param name="locale">The locale used to select the localized version of the option item.</param>
    /// <returns>A <see cref="Task{TResult}"/> that yields the matching <see cref="OptionList"/>, or <c>null</c> if no item is found.</returns>
    Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale);
    /// <summary>
    /// Asynchronously retrieves an <see cref="OptionList"/> identified by the given master and option identifiers.
    /// </summary>
    /// <param name="masterId">The identifier of the master record that owns the option list.</param>
    /// <param name="optionId">The identifier of the specific option item to locate within the master.</param>
    /// <returns>A <see cref="Task{OptionList}"/> that yields the matching <see cref="OptionList"/>, or <c>null</c> when no item is found.</returns>
    Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId);
    /// <summary>
    /// Asynchronously retrieves all items of type T.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains an enumerable collection of all items of type T.</returns>
    Task<IEnumerable<T>> GetAll();
    /// <summary>
    /// Retrieves all master list entries without applying optional filters or including related option data.
    /// Used to fetch the complete set of master list records for scenarios such as full enumeration or bulk operations.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation, containing an <see cref="IEnumerable{MasterListDto}"/> with all available master list entries.</returns>
    Task<IEnumerable<MasterListDto>> GetAllWithoutOptions();
    /// <summary>
    /// Asynchronously finds and returns an entity of type <typeparamref name="T"/> matching the specified <paramref name="name"/>.
    /// Returns <c>null</c> when no matching entity is found.
    /// </summary>
    /// <param name="name">The name used to look up the entity.</param>
    /// <returns>A task that represents the asynchronous lookup, containing the matched entity of type <typeparamref name="T"/> or <c>null</c> if no match exists.</returns>
    Task<T?> FindByName(string name);
    /// <summary>
    /// Retrieves a master list of option list entries filtered by the specified identifier and an optional text search that performs a contains match.
    /// </summary>
    /// <param name="id">The identifier used to scope the option list entries to be returned.</param>
    /// <param name="textSearch">An optional text used to filter entries whose content contains the specified value; may be null to skip text-based filtering.</param>
    /// <returns>A task representing the asynchronous operation, containing a list of <see cref="OptionList"/> entries that match the identifier and the optional text search criteria.</returns>
    Task<List<OptionList>> GetMasterListByIdAndTextSearchContaining(ObjectId id, string? textSearch);
    /// <summary>
    /// Asynchronously adds a <see cref="FilterOptionListElement"/> to the master option list identified by the given <see cref="ObjectId"/>.
    /// </summary>
    /// <param name="id">The identifier of the master option list to which the element will be added.</param>
    /// <param name="opt">The filter option list element to add to the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the resulting <see cref="OptionList"/>, or <c>null</c> if no list is returned.</returns>
    Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt);
    /// <summary>
    /// Updates an existing master list option identified by the specified identifier using the provided option data and locale, returning the updated option list.
    /// </summary>
    /// <param name="id">The unique identifier of the master list option to update.</param>
    /// <param name="newOpt">The new option list data to apply to the master list option.</param>
    /// <param name="locale">The locale used for the update operation.</param>
    /// <returns>A task that represents the asynchronous operation, containing the updated <see cref="OptionList"/> if found, or <c>null</c> if no matching master list option exists.</returns>
    Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale);
    /// <summary>
    /// Updates an existing master list option identified by the given id with the provided data, returning the updated option or null if no matching option is found.
    /// </summary>
    /// <param name="id">The unique identifier of the master list option to update.</param>
    /// <param name="newOpt">The new option data to replace the existing master list option.</param>
    /// <returns>A task representing the asynchronous operation, containing the updated <see cref="OptionList"/>, or null if no option with the specified id exists.</returns>
    Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList newOpt);
    /// <summary>
    /// Updates an existing master list option identified by the specified id with the provided new option data.
    /// </summary>
    /// <param name="id">The unique identifier of the master list option to update.</param>
    /// <param name="newOpt">The new option data to apply to the existing master list option.</param>
    /// <returns>A task that represents the asynchronous operation, containing the updated <see cref="OptionList"/>, or <c>null</c> if no matching option was found.</returns>
    Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt);
    /// <summary>
    /// Deletes a master list option identified by the specified option ID.
    /// </summary>
    /// <param name="id">The identifier of the master list containing the option to delete.</param>
    /// <param name="deleteOptId">The identifier of the option to be deleted from the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a boolean indicating whether the option was successfully deleted.</returns>
    Task<bool> DeleteMasterListOption(ObjectId id, ObjectId deleteOptId);
    /// <summary>
    /// Updates the option details of an existing entry in the master list identified by the specified id.
    /// </summary>
    /// <param name="id">The unique identifier of the master list entry to update.</param>
    /// <param name="opt">The update payload containing the new option details to apply.</param>
    /// <returns>A task that represents the asynchronous operation, containing the updated master list details, or null if no matching entry is found.</returns>
    Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id, UpdateMasterListDetailsDto opt);
    /// <summary>
    /// Updates the name of an existing master list identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list to update.</param>
    /// <param name="name">The new name to assign to the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the master list was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateMasterListName(ObjectId id, string name);
    /// <summary>
    /// Asynchronously updates the description of a master list identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list to update.</param>
    /// <param name="description">The new description to set for the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <see langword="true"/> if the update was successful; otherwise, <see langword="false"/>.</returns>
    Task<bool> UpdateMasterListDescription(ObjectId id, string description);
    /// <summary>
    /// Asynchronously removes the specified option from the master list associated with the given identifier.
    /// </summary>
    /// <param name="id">The identifier of the master list from which the option will be removed.</param>
    /// <param name="oldOpt">The option to be removed from the master list.</param>
    /// <returns>A task that represents the asynchronous removal operation. The task result contains true if the option was successfully removed; otherwise, false.</returns>
    Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt);
    /// <summary>
    /// Retrieves a paginated master list using the specified pagination filter, returning a fluent queryable result.
    /// </summary>
    /// <param name="filter">The pagination filter that defines the paging criteria applied to the master list query.</param>
    /// <returns>An <see cref="IFindFluent{TDocument, TProjection}"/> that represents the paginated queryable master list.</returns>
    IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter);
    /// <summary>
    /// Retrieves a paginated collection of options associated with the specified list identifier, applying the provided pagination filter to control the result set.
    /// </summary>
    /// <param name="filter">The pagination filter defining page size, page number, and related pagination constraints.</param>
    /// <param name="listId">The unique identifier of the list whose options should be retrieved.</param>
    /// <returns>A task representing the asynchronous operation, containing a list of <see cref="OptionList"/> items for the requested page.</returns>
    Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId);
    /// <summary>
    /// Asynchronously counts the number of items and returns the total.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains the total count of items.</returns>
    Task<int> Count();
    /// <summary>
    /// Retrieves a master list of <see cref="OptionList"/> entries identified by the given id, optionally applying the provided search and filtering options.
    /// </summary>
    /// <param name="id">The identifier of the master list to retrieve.</param>
    /// <param name="filterOption">Optional filter criteria used to narrow the returned options. May be <c>null</c> to return the full list without additional filtering.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of <see cref="OptionList"/> items that match the specified id and filter, or an empty list if no matching entries are found.</returns>
    Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filterOption);
}