using adas_core.Domain.Enums;
using adas_core.Domain.Models.DTO.Display;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Application.Repositories.Interfaces;

public interface IDisplayConfigRepository : IMongoRepository<DisplayConfig>
{
    /// <summary>
    /// Asynchronously retrieves all display configurations.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of all <see cref="DisplayConfig"/> entries.</returns>
    Task<List<DisplayConfig>> GetAll();
    /// <summary>
    /// Retrieves a paginated set of <see cref="DisplayConfig"/> entities projected as <see cref="DisplayConfigSummary"/>.
    /// </summary>
    /// <param name="request">The pagination filter applied to the query.</param>
    /// <returns>An <see cref="IFindFluent{TDocument, TProjection}"/> that produces the paginated <see cref="DisplayConfigSummary"/> results.</returns>
    IFindFluent<DisplayConfig, DisplayConfigSummary> GetAllPaginated(PaginationFilter request);
    /// <summary>
    /// Asynchronously retrieves the list of display configurations that match the specified display type.
    /// </summary>
    /// <param name="type">The display type used to filter the returned display configurations.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of <see cref="DisplayConfig"/> entries matching the specified type.</returns>
    Task<List<DisplayConfig>> GetByType(DisplayConfigEnums.DisplayType type);
    /// <summary>
    /// Retrieves a <see cref="DisplayConfig"/> entity by its unique identifier asynchronously.
    /// Returns <c>null</c> when no matching display configuration is found.
    /// </summary>
    /// <param name="id">The unique identifier of the display configuration to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="DisplayConfig"/> if found, or <c>null</c> if no matching record exists.</returns>
    Task<DisplayConfig?> GetById(ObjectId id);
    /// <summary>
    /// Asynchronously retrieves the default <see cref="DisplayConfig"/> for the specified display type.
    /// Returns <c>null</c> when no default configuration is found for the requested type.
    /// </summary>
    /// <param name="type">The display type used to look up the default configuration.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the default <see cref="DisplayConfig"/> for the given type, or <c>null</c> if no default exists.</returns>
    Task<DisplayConfig?> GetDefault(DisplayConfigEnums.DisplayType type);
    /// <summary>
    /// Asynchronously inserts a new <see cref="DisplayConfig"/> and returns the persisted entity, typically populated with any server-generated values.
    /// </summary>
    /// <param name="config">The <see cref="DisplayConfig"/> to insert.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the inserted <see cref="DisplayConfig"/>, or <see langword="null"/> when no result is returned.</returns>
    Task<DisplayConfig?> InsertOneAsyncAndReturn(DisplayConfig config);
    /// <summary>
    /// Updates the smart display configuration identified by the specified ID with the provided new configuration.
    /// </summary>
    /// <param name="displayConfigId">The unique identifier of the smart display configuration to update.</param>
    /// <param name="newDisplayConfig">The new smart display configuration to apply.</param>
    /// <returns>A task that represents the asynchronous update operation, containing the updated smart display configuration, or null if no configuration with the given ID was found.</returns>
    Task<SmartDisplay?> UpdateSmartDisplay(ObjectId displayConfigId, SmartDisplay? newDisplayConfig);

    /// <summary>
    /// Updates an existing display nurse configuration identified by the specified identifier.
    /// </summary>
    /// <param name="displayConfigId">The identifier of the display nurse configuration to update.</param>
    /// <param name="newDisplayConfig">The new display nurse configuration data, or null if not provided.</param>
    /// <param name="nurseObs">The list of nurse observations to associate with the configuration.</param>
    /// <returns>A task that represents the asynchronous operation, containing the updated <see cref="DisplayNurse"/> or null if not found.</returns>
    Task<DisplayNurse?> UpdateDisplayNurse(ObjectId displayConfigId, DisplayNurseDto? newDisplayConfig,
            List<string> nurseObs);

    /// <summary>
    /// Retrieves the default <see cref="DisplayConfig"/> associated with the specified unit and display type.
    /// Returns <c>null</c> when no matching default configuration exists.
    /// </summary>
    /// <param name="unitId">The identifier of the unit whose default display configuration is being requested.</param>
    /// <param name="displayType">The display type used to filter the configuration lookup.</param>
    /// <returns>A task containing the matching <see cref="DisplayConfig"/>, or <c>null</c> if no default configuration is found for the given unit and display type.</returns>
    Task<DisplayConfig?> GetDefaultByUnitIdAndType(ObjectId unitId, DisplayConfigEnums.DisplayType displayType);
    /// <summary>
    /// Asynchronously updates the color configuration for the specified config display entry.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The unique identifier of the config display whose color configuration will be updated.</param>
    /// <param name="colorConfig">The new color configuration to apply to the config display.</param>
    /// <returns>A task that resolves to <c>true</c> if the color configuration was successfully updated; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateConfigColor(ObjectId objectIdConfigDisplay, ColorConfig colorConfig);
    /// <summary>
    /// Updates the home banner configuration identified by the specified config display ObjectId with the provided list of banner items.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The ObjectId of the config display whose home banner set will be updated.</param>
    /// <param name="bannerItems">The collection of banner items to apply to the home banner set.</param>
    /// <returns>A task that resolves to <c>true</c> if the home banner set was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateSetHomeBanner(ObjectId objectIdConfigDisplay, List<BannerItem> bannerItems);
    /// <summary>
    /// Updates the base display configuration identified by the specified object identifier with the provided configuration data.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The object identifier of the configuration display entry to update.</param>
    /// <param name="baseConfig">The new base display configuration values to apply.</param>
    /// <returns>A task that represents the asynchronous operation. The result is <c>true</c> if the update succeeded; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateBaseConfig(ObjectId objectIdConfigDisplay, DisplayConfig baseConfig);
    /// <summary>
    /// Updates an existing header configuration associated with the specified configuration display identifier.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The unique identifier of the configuration display whose header configuration is being updated.</param>
    /// <param name="headerConfig">The new header configuration values to apply.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the header configuration was successfully updated; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateHeaderConfig(ObjectId objectIdConfigDisplay, HeaderConfig headerConfig);
    /// <summary>
    /// Updates the hospital name associated with the specified display configuration.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the display configuration to update.</param>
    /// <param name="name">The new hospital name to apply to the display configuration.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the update succeeded; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateDisplayConfigHospitalName(ObjectId objectIdConfigDisplay, string name);
    /// <summary>
    /// Updates the field list associated with the specified configuration display.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the configuration display whose field list is being updated.</param>
    /// <param name="fields">The list of fields to apply to the configuration display.</param>
    /// <returns>A task that resolves to <c>true</c> if the field list was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateFieldList(ObjectId objectIdConfigDisplay, List<Field> fields);
    /// <summary>
    /// Deletes a display configuration identified by the specified object ID.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The object ID of the display configuration to delete.</param>
    /// <returns>A task that represents the asynchronous delete operation. The task result contains the deleted display configuration, or null if no configuration was found with the specified ID.</returns>
    Task<DisplayConfig?> DeleteDisplayConfig(ObjectId objectIdConfigDisplay);
    /// <summary>
    /// Retrieves all display configurations in a compact, minimal representation.
    /// </summary>
    /// <returns>A task containing a list of <see cref="DisplayConfigMinimalResponse"/> objects representing the display configurations.</returns>
    Task<List<DisplayConfigMinimalResponse>> GetAllCompact();
    /// <summary>
    /// Retrieves all object identifiers associated with the specified card configuration identifier.
    /// </summary>
    /// <param name="cardConfigId">The identifier of the card configuration whose related objects should be returned.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="ObjectId"/> values linked to the given card configuration.</returns>
    Task<List<ObjectId>> GetAllByCardConfigId(ObjectId cardConfigId);
    /// <summary>
    /// Asynchronously retrieves a list of ObjectIds associated with the specified card configuration that are marked as rotating.
    /// </summary>
    /// <param name="cardConfigId">The ObjectId of the card configuration used to filter the results.</param>
    /// <returns>A task representing the asynchronous operation, containing a list of ObjectIds that match the given card configuration and rotating criteria.</returns>
    Task<List<ObjectId>> GetAllByCardConfigIdAndRotating(ObjectId cardConfigId);
    /// <summary>
    /// Updates the card configuration identifier for the specified display configuration and result.
    /// </summary>
    /// <param name="displayConfigId">The identifier of the display configuration whose card configuration will be updated.</param>
    /// <param name="resultId">The identifier of the result associated with the card configuration update.</param>
    /// <returns>A task that resolves to <c>true</c> if the update succeeded; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateCardConfigId(ObjectId? displayConfigId, ObjectId? resultId);
    /// <summary>
    /// Adds a chart identifier to the specified display configuration asynchronously.
    /// </summary>
    /// <param name="displayConfigId">The identifier of the display configuration to which the chart ID will be added, or <c>null</c> when no specific configuration is targeted.</param>
    /// <param name="newChartIdToAdd">The chart identifier to add.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the chart identifier was successfully added; otherwise, <c>false</c>.</returns>
    Task<bool> AddChartId(ObjectId? displayConfigId, ObjectId newChartIdToAdd);
    /// <summary>
    /// Updates the configuration of a chart that was previously deleted, using the specified identifier.
    /// </summary>
    /// <param name="deletedId">The identifier of the deleted chart configuration to update.</param>
    /// <returns>A task that represents the asynchronous update operation, containing the result of the update.</returns>
    Task<UpdateResult> UpdateDeletedChartConfig(ObjectId deletedId);
    /// <summary>
    /// Asynchronously retrieves the chart configuration associated with the specified chart object identifier.
    /// </summary>
    /// <param name="objectIdConfigChart">The unique object identifier of the chart configuration to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation, containing the <see cref="ChartConfig"/> associated with the specified identifier.</returns>
    Task<ChartConfig> GetChartConfig(ObjectId objectIdConfigChart);
    /// <summary>
    /// Asynchronously updates the detail configuration identifier, associating it with the specified result identifier.
    /// </summary>
    /// <param name="displayConfigId">The nullable identifier of the display configuration to update.</param>
    /// <param name="resultId">The nullable identifier of the result to associate with the configuration.</param>
    /// <returns>A task that represents the asynchronous operation, containing a boolean indicating whether the update was successful.</returns>
    Task<bool> UpdateDetailConfigId(ObjectId? displayConfigId, ObjectId? resultId);
    /// <summary>
    /// Asynchronously retrieves a list of identifiers associated with the specified card detail base configuration.
    /// </summary>
    /// <param name="baseConfigId">The identifier of the card detail base configuration to filter by.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="ObjectId"/> values matching the provided base configuration identifier.</returns>
    Task<List<ObjectId>> GetAllByCardDetailConfigId(ObjectId baseConfigId);
}