using adas_core.Domain.Enums;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IMasterListServiceFactory
{
    /// <summary>
    /// Gets the service object of the specified type.
    /// </summary>
    /// <param name="serviceType">An object that specifies the type of service object to get.</param>
    /// <returns>
    /// A service object of type <paramref name="serviceType"/>, or <c>null</c> if there is no service
    /// object of that type registered.
    /// </returns>
    object GetService(Type serviceType);
    /// <summary>
    /// Retrieves a service instance from the master list based on the specified service name.
    /// </summary>
    /// <param name="serviceName">The <see cref="MasterListType"/> identifier used to look up the desired service.</param>
    /// <returns>An <see cref="object"/> representing the resolved service, or <see langword="null"/> if no matching service is found.</returns>
    object GetService(MasterListType serviceName);
    /// <summary>
    /// Retrieves a typed representation of the specified <paramref name="masterList"/> based on the given <paramref name="masterListType"/>.
    /// </summary>
    /// <param name="masterListType">The type that determines how the master list should be converted or filtered.</param>
    /// <param name="masterList">The master list to be returned in a typed form.</param>
    /// <returns>A typed object representing the master list, or <c>null</c> if no matching type is found.</returns>
    object? GetTypedMasterList(MasterListType masterListType, MasterList masterList);
    /// <summary>
    /// Gets the specific <see cref="Type"/> associated with the given master list type, mapping the master list category to its corresponding implementation type.
    /// </summary>
    /// <param name="masterListType">The master list type whose associated <see cref="Type"/> should be returned.</param>
    /// <returns>The <see cref="Type"/> that corresponds to the specified <paramref name="masterListType"/>.</returns>
    Type GetMasterListSpecificType(MasterListType masterListType);
    /// <summary>
    /// Inserts a new <see cref="MasterList"/> record based on the specified <paramref name="masterListType"/>.
    /// </summary>
    /// <param name="masterListType">The type of master list to insert.</param>
    /// <param name="masterList">The master list entity to be inserted.</param>
    /// <returns>A task that represents the asynchronous insert operation. The result contains the inserted master list data, or <c>null</c> if the insert was not successful.</returns>
    Task<object?> InsertMasterList(MasterListType masterListType, MasterList masterList);
    /// <summary>
    /// Asynchronously updates an existing master list entry based on the specified master list type and master list data.
    /// </summary>
    /// <param name="masterListType">The type of master list to update, used to determine the target list or category.</param>
    /// <param name="masterList">The master list entity containing the updated data to be persisted.</param>
    /// <returns>A task that represents the asynchronous update operation. The result is an object containing the updated master list information, or <c>null</c> if no matching record was found.</returns>
    Task<object?> UpdateMasterList(MasterListType masterListType, MasterList masterList);
    /// <summary>
    /// Retrieves a master list entry by its identifier and type, optionally filtered by the specified data locale.
    /// </summary>
    /// <param name="masterListType">The type of the master list to query.</param>
    /// <param name="masterListId">The unique identifier of the master list entry to retrieve.</param>
    /// <param name="dataLocale">The optional locale used to resolve localized data; when null, no locale filtering is applied.</param>
    /// <returns>A task that yields the matching master list entry as an object, or null if no entry is found.</returns>
    Task<object?> GetMasterListById(MasterListType masterListType, ObjectId masterListId, LocaleEnum? dataLocale);
    /// <summary>
    /// Retrieves a list of nurse observation entries as string values.
    /// </summary>
    /// <returns>A <see cref="List{T}"/> of <see cref="string"/> containing the nurse observation data.</returns>
    List<string> StringNurseObs();
    /// <summary>
    /// Retrieves a translated <see cref="Patient"/> based on the provided <paramref name="unit"/> and <paramref name="locale"/>.
    /// Returns <c>null</c> when the <paramref name="patient"/>, <paramref name="unit"/>, or <paramref name="locale"/> is not provided or no translation is found.
    /// </summary>
    /// <param name="unit">The organizational unit context used to look up the translation. May be <c>null</c>.</param>
    /// <param name="locale">The target locale for the translation. May be <c>null</c>.</param>
    /// <param name="patient">The patient to be translated. May be <c>null</c>.</param>
    /// <returns>A <see cref="Task{TResult}"/> that resolves to the translated <see cref="Patient"/>, or <c>null</c> if no translation is available.</returns>
    Task<Patient?> GetPatientTraslated(Unit? unit, LocaleEnum? locale, Patient? patient);

    /// <summary>
    /// Retrieves a master list option by its identifier, optionally localized to the specified data locale.
    /// Returns <see langword="null"/> if no matching option is found.
    /// </summary>
    /// <param name="masterListType">The type of master list to search within.</param>
    /// <param name="masterListId">The identifier of the master list containing the option.</param>
    /// <param name="masterListOptionId">The identifier of the master list option to retrieve.</param>
    /// <param name="dataLocale">The optional locale used to localize the returned option data.</param>
    /// <returns>A task that yields the matching master list option as an <see cref="object"/>, or <see langword="null"/> if not found.</returns>
    Task<object?> GetMasterListOptionById(MasterListType masterListType, ObjectId masterListId,
            ObjectId masterListOptionId,
            LocaleEnum? dataLocale);
}