using adas_core.Domain.Enums;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.Responses;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IMasterListService<T> where T : MasterList
{
    /// <summary>
    /// Asynchronously retrieves the complete master list of items of type <typeparamref name="T"/>.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="IEnumerable{T}"/> with all items from the master list.</returns>
    Task<IEnumerable<T>> GetAllMasterList();
    /// <summary>
    /// Retrieves all master list entries, excluding items categorized as options.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a collection of <see cref="MasterListDto"/> items representing the master list without options.</returns>
    Task<IEnumerable<MasterListDto>> GetAllMasterListWithoutOptions();
    /// <summary>
    /// Retrieves a paginated collection of master list items with their associated options based on the specified pagination filter.
    /// </summary>
    /// <param name="request">The pagination filter containing paging criteria such as page number and page size.</param>
    /// <returns>A task that represents the asynchronous operation, containing an enumerable collection of <see cref="MasterListWithPaginatedOptionsDto"/> items for the requested page.</returns>
    Task<IEnumerable<MasterListWithPaginatedOptionsDto>> GetAllMasterListWithPaginatedOptions(PaginationFilter request);
    /// <summary>
    /// Retrieves a master list entry identified by the specified <paramref name="id"/>, optionally resolving localized content based on the provided <paramref name="locale"/>. Returns <c>null</c> when no matching entry is found.
    /// </summary>
    /// <param name="id">The unique identifier of the master list entry to retrieve.</param>
    /// <param name="locale">The optional locale used to resolve localized fields; when <c>null</c>, a default or non-localized representation is returned.</param>
    /// <returns>A task that resolves to the matching master list entry of type <typeparamref name="T"/>, or <c>null</c> if the entry does not exist.</returns>
    Task<T?> GetMasterListById(ObjectId id, LocaleEnum? locale);

    /// <summary>
    /// Asynchronously retrieves a master list along with its paginated options identified by the specified id.
    /// Returns null when no master list is found for the given identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list to retrieve.</param>
    /// <param name="request">The pagination filter used to control the paginated options returned with the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="MasterListWithPaginatedOptionsDto"/> if a matching master list is found, otherwise null.</returns>
    Task<MasterListWithPaginatedOptionsDto?> GetMasterListByIdWithPaginatedOptions(ObjectId id,
            PaginationFilter request);

    /// <summary>
    /// Retrieves the list of master list option names associated with the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list whose option names are being retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of option names for the specified master list.</returns>
    Task<List<string>> GetMasterListOptionsNamesById(ObjectId id);
    /// <summary>
    /// Retrieves a master list of <see cref="OptionList"/> entries filtered by the specified identifier and an optional text search criterion.
    /// </summary>
    /// <param name="id">The unique identifier used to scope the master list lookup.</param>
    /// <param name="textSearch">An optional text string used to further filter the results; may be <c>null</c> to return all matching entries.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="OptionList"/> items matching the provided identifier and text search.</returns>
    Task<List<OptionList>> GetMasterListByIdAndTextSearch(ObjectId id, string? textSearch);
    /// <summary>
    /// Asynchronously retrieves a master list of options associated with the specified identifier, applying the provided search and filter criteria.
    /// </summary>
    /// <param name="id">The identifier used to locate the master list to retrieve.</param>
    /// <param name="filterOption">The filter and search options used to refine the returned list.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of <see cref="OptionList"/> entries that match the specified id and filter options.</returns>
    Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement filterOption);
    /// <summary>
    /// Asynchronously retrieves a master list that matches the specified name.
    /// </summary>
    /// <param name="name">The name used to look up the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The result is the matching master list of type <typeparamref name="T"/>, or <c>null</c> if no master list with the specified name is found.</returns>
    Task<T?> GetMasterListByName(string name);
    /// <summary>
    /// Inserts the specified item into the master list and returns the resulting entry, or <c>null</c> if the operation did not produce a result.
    /// </summary>
    /// <param name="item">The item to insert into the master list.</param>
    /// <returns>A <see cref="Task{T}"/> that resolves to the inserted item, or <c>null</c> when no result is available.</returns>
    Task<T?> InsertMasterList(T item);
    /// <summary>
    /// Updates the master list with the specified item.
    /// </summary>
    /// <param name="item">The item to be updated in the master list.</param>
    /// <returns>A task that represents the asynchronous update operation, containing the updated item or <c>null</c> if the update could not be performed.</returns>
    Task<T?> UpdateMasterList(T item);
    /// <summary>
    /// Deletes a master list identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list to delete.</param>
    Task DeleteMasterListById(ObjectId id);
    /// <summary>
    /// Adds the specified option element to the master option list identified by the given identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master option list to which the option will be added.</param>
    /// <param name="opt">The filter option list element to append to the master list.</param>
    /// <returns>A task that returns the updated <see cref="OptionList"/>, or <c>null</c> if the master list could not be found.</returns>
    Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt);
    /// <summary>
    /// Updates an option in a master list, localized for the specified locale, and returns the updated option list.
    /// </summary>
    /// <param name="id">The identifier of the option to update.</param>
    /// <param name="opt">The option data to apply to the existing entry.</param>
    /// <param name="typeName">The name of the master list type that owns the option.</param>
    /// <param name="locale">The locale used to resolve or apply localized values.</param>
    /// <returns>A task that returns the updated <see cref="OptionList"/>, or <c>null</c> if the option could not be found.</returns>
    Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList opt, string typeName, LocaleEnum locale);
    /// <summary>
    /// Updates the full master list option identified by the specified identifier and type name.
    /// </summary>
    /// <param name="id">The identifier of the option to update.</param>
    /// <param name="opt">The option list containing the updated values.</param>
    /// <param name="typeName">The name of the type associated with the master list option.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the updated <see cref="OptionList"/>, or <c>null</c> if the option was not found.</returns>
    Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList opt, string typeName);
    /// <summary>
    /// Updates a master list option for the specified type with the provided option data.
    /// </summary>
    /// <param name="id">The unique identifier of the option to update.</param>
    /// <param name="opt">The option data to apply to the master list.</param>
    /// <param name="typeName">The name of the master list type containing the option.</param>
    /// <returns>The updated <see cref="OptionList"/>, or null if the option is not found.</returns>
    Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList opt, string typeName);
    /// <summary>
    /// Asynchronously retrieves an option list item identified by the specified master ID, option ID, and locale.
    /// </summary>
    /// <param name="masterId">The identifier of the master entity that owns the option list.</param>
    /// <param name="optionId">The identifier of the specific option item to find.</param>
    /// <param name="locale">The locale used to retrieve the localized option item.</param>
    /// <returns>A task that represents the asynchronous operation, containing 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>
    /// Updates the option details of a master list entry identified by the specified id.
    /// </summary>
    /// <param name="id">The identifier of the master list entry to update.</param>
    /// <param name="opt">The master list details to apply to the entry.</param>
    /// <returns>A task that returns 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 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 successfully updated; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateMasterListName(ObjectId id, string name);
    /// <summary>
    /// Updates the description (name) of a master list entry identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the master list entry to update.</param>
    /// <param name="name">The new description to apply to the master list entry.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the update was successful; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateMasterListDescription(ObjectId id, string name);
    /// <summary>
    /// Asynchronously removes the specified option from the master list identified by the given id.
    /// </summary>
    /// <param name="id">The identifier of the master list from which the option will be removed.</param>
    /// <param name="oldOpt">The option entry to be removed from the master list.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the option was successfully removed; otherwise, <c>false</c>.</returns>
    Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt);
    /// <summary>
    /// Asynchronously retrieves the total count of all items in the master list.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains the total number of items in the master list.</returns>
    Task<int> GetAllMasterListCount();
    /// <summary>
    /// Retrieves a paginated master list of items based on the specified filter criteria.
    /// </summary>
    /// <param name="filter">The pagination filter that defines paging parameters such as page number and page size.</param>
    /// <returns>A task that represents the asynchronous operation, containing the paginated response with the requested master list items.</returns>
    Task<PaginationResponse<T>> GetPaginatedMasterList(PaginationFilter filter);
    /// <summary>
    /// Asynchronously deletes a master list option identified by the supplied identifiers.
    /// </summary>
    /// <param name="id">The identifier of the master list that contains the option to delete.</param>
    /// <param name="optId">The identifier of the specific option to remove from the master list.</param>
    /// <param name="typeName">The name of the master list type to which the option belongs.</param>
    /// <returns>A task that resolves to <c>true</c> if the option was successfully deleted; otherwise, <c>false</c>.</returns>
    Task<bool> DeleteMasterListOption(ObjectId id, ObjectId optId, string typeName);

    /// <summary>
    /// Asynchronously retrieves a paginated master list along with its associated paginated options.
    /// </summary>
    /// <param name="listFilter">The pagination filter applied to the master list results.</param>
    /// <param name="optionsFilter">The pagination filter applied to the associated options.</param>
    /// <returns>A task that represents the asynchronous operation, containing the paginated response with master list and options data.</returns>
    Task<PaginationResponse<MasterListWithPaginatedOptionsDto>> GetPaginatedMasterListWithPaginatedOptions(
            PaginationFilter listFilter, PaginationFilter optionsFilter);

    /// <summary>
    /// Retrieves a paginated collection of options associated with the specified list.
    /// </summary>
    /// <param name="filter">The pagination parameters used to control the page size and page index of the returned results.</param>
    /// <param name="listId">The identifier of the list whose options should be retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a <see cref="PaginationResponse{OptionList}"/> with the requested options.</returns>
    Task<PaginationResponse<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId);
    /// <summary>
    /// Retrieves the associated list identifier for the given object based on the specified master list types.
    /// </summary>
    /// <param name="id">The identifier of the object whose associated list is being requested.</param>
    /// <param name="masterListType1">The first master list type used to determine the association.</param>
    /// <param name="masterListType2">The second master list type used to determine the association.</param>
    /// <returns>A task that returns the associated <see cref="ObjectId"/> if found, or <c>null</c> if no association exists.</returns>
    Task<ObjectId?> GetAssociatedList(ObjectId id, MasterListType masterListType1, MasterListType masterListType2);
    /// <summary>
    /// Retrieves the available options associated with the specified list identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the list whose options are being retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of option strings for the specified list.</returns>
    Task<List<string>> GetOptionsOfList(ObjectId id);
}