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;

namespace adas_core.Application.Services.Interfaces;

public interface IDisplayConfigService
{
    /// <summary>
    /// Retrieves all display configurations asynchronously.
    /// </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 list of display configurations in a compact (minimal) representation.
    /// </summary>
    /// <param name="request">The pagination filter that controls page size, page number, and sorting criteria.</param>
    /// <returns>A task that represents the asynchronous operation, containing a <see cref="PaginationResponse{T}"/> with the compact display configuration entries.</returns>
    Task<PaginationResponse<DisplayConfigMinimalResponse>> GetAllCompactPaginated(PaginationFilter request);
    /// <summary>
    /// Retrieves a list of display configurations filtered by the specified display type.
    /// </summary>
    /// <param name="type">The display type used to filter the configurations.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="DisplayConfig"/> objects matching the specified type.</returns>
    Task<List<DisplayConfig>> GetByType(DisplayConfigEnums.DisplayType type);
    /// <summary>
    /// Asynchronously retrieves a <see cref="DisplayConfig"/> by its identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the display configuration to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation, containing the <see cref="DisplayConfig"/> matching the specified identifier.</returns>
    Task<DisplayConfig> GetById(ObjectId id);
    /// <summary>
    /// Asynchronously retrieves a <see cref="DisplayConfig"/> identified by the specified configuration identifier, unit identifier, and display type.
    /// </summary>
    /// <param name="configId">The optional identifier of the display configuration to look up; may be <c>null</c> when searching without a specific configuration.</param>
    /// <param name="unitId">The identifier of the unit the display configuration belongs to.</param>
    /// <param name="displayType">The display type used to filter or scope the lookup.</param>
    /// <returns>A <see cref="Task{DisplayConfig}"/> that resolves to the matching <see cref="DisplayConfig"/>, or <c>null</c> if no configuration is found.</returns>
    Task<DisplayConfig?> GetById(ObjectId? configId, ObjectId unitId, DisplayConfigEnums.DisplayType displayType);
    /// <summary>
    /// Inserts a single display configuration asynchronously and returns the resulting configuration, or null when no record is produced.
    /// </summary>
    /// <param name="config">The display configuration to insert.</param>
    /// <returns>A task that represents the asynchronous insert operation, containing the inserted <see cref="DisplayConfig"/> or null.</returns>
    Task<DisplayConfig?> InsertOne(DisplayConfig config);
    /// <summary>
    /// Inserts a new display configuration in a minimal fashion and returns the created <see cref="DisplayConfig"/>, or <c>null</c> when no configuration could be produced.
    /// </summary>
    /// <param name="config">The data transfer object containing the values used to create the new display configuration.</param>
    /// <returns>A <see cref="Task{TResult}"/> that yields the created <see cref="DisplayConfig"/> when successful, or <c>null</c> when no result is available.</returns>
    Task<DisplayConfig?> InsertOneMinimal(CreateDisplayConfigDto config);
    /// <summary>
    /// Performs a test insertion operation that returns a <see cref="DisplayConfig"/> instance, used to validate insertion behavior.
    /// </summary>
    /// <returns>A <see cref="Task{DisplayConfig}"/> representing the asynchronous test insertion result.</returns>
    Task<DisplayConfig> InsertOneTest();
    /// <summary>
    /// Updates the display configuration identified by the specified identifier with the provided new configuration data.
    /// </summary>
    /// <param name="displayConfigId">The unique identifier of the display configuration to update.</param>
    /// <param name="newDisplayConfig">The new display configuration data to apply to the existing configuration.</param>
    /// <returns>The updated <see cref="DisplayConfig"/>, or <c>null</c> if no display configuration with the specified identifier is found.</returns>
    Task<DisplayConfig?> UpdateConfig(ObjectId displayConfigId, object newDisplayConfig);
    /// <summary>
    /// Updates the list of fields associated with the specified configuration display.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the configuration display whose field list will be updated.</param>
    /// <param name="fields">The list of fields to be applied to the configuration display.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a value indicating whether the update was successful.</returns>
    Task<bool> UpdateFieldList(ObjectId objectIdConfigDisplay, List<Field> fields);
    /// <summary>
    /// Updates the color configuration for the specified config display.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the config display whose color configuration will be updated.</param>
    /// <param name="colorConfigDto">The color configuration data to apply to the config display.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the update was successful; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateConfigColor(ObjectId objectIdConfigDisplay, ColorConfig colorConfigDto);
    /// <summary>
    /// Asynchronously updates the header configuration associated with the specified config display identifier.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the config display whose header configuration will be updated.</param>
    /// <param name="headerConfig">The new header configuration to apply.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the update was successful; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateHeaderConfig(ObjectId objectIdConfigDisplay, HeaderConfig headerConfig);
    /// <summary>
    /// Updates the home banner configuration for the specified config display with the provided list of banner items.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the config display whose home banner will be updated.</param>
    /// <param name="bannerItems">The list of banner items to set as the home banner configuration.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the home banner was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateSetHomeBanner(ObjectId objectIdConfigDisplay, List<BannerItem> bannerItems);
    /// <summary>
    /// Updates the base display configuration with the specified settings.
    /// </summary>
    /// <param name="baseConfig">The display configuration to apply as the new base configuration.</param>
    /// <returns>A task that represents the asynchronous update operation. The task result contains a boolean value indicating whether the update was successful.</returns>
    Task<bool> UpdateBaseConfig(DisplayConfig baseConfig);
    /// <summary>
    /// Asynchronously updates the hospital name associated with the specified display configuration.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The identifier of the display configuration whose hospital name will be updated.</param>
    /// <param name="name">The new hospital name to apply to the display configuration.</param>
    /// <returns>A task that resolves to <c>true</c> if the update was applied successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateDisplayConfigHospitalName(ObjectId objectIdConfigDisplay, string name);
    /// <summary>
    /// Deletes a display configuration identified by the specified object identifier.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The unique identifier of the display configuration to delete.</param>
    /// <returns>A task that represents the asynchronous delete operation. The task result contains a boolean value indicating whether the display configuration was successfully deleted.</returns>
    Task<bool> DeleteDisplayConfig(ObjectId objectIdConfigDisplay);
    /// <summary>
    /// Asynchronously retrieves the default display configuration for the specified display type.
    /// </summary>
    /// <param name="type">The display type used to look up the default configuration.</param>
    /// <returns>A task that represents the asynchronous operation, containing the default <see cref="DisplayConfig"/> for the given display type, or <c>null</c> if no default configuration is available.</returns>
    Task<DisplayConfig?> GetDefaultConfig(DisplayConfigEnums.DisplayType type);
    /// <summary>
    /// Retrieves the list of display configuration locations associated with the specified configuration display identifier.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The ObjectId of the configuration display whose locations are to be retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of DisplayConfigLocationDto objects for the specified configuration display.</returns>
    Task<List<DisplayConfigLocationDto>> GetDisplayConfigLocations(ObjectId objectIdConfigDisplay);
    /// <summary>
    /// Asynchronously retrieves all display configurations in a compact (minimal) representation.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="DisplayConfigMinimalResponse"/> objects representing the compact display configurations.</returns>
    Task<List<DisplayConfigMinimalResponse>> GetAllCompact();

    /// <summary>
    /// Inserts a new display configuration record using a predefined template, optionally scoped to a specific hospital context.
    /// </summary>
    /// <param name="objectId">The identifier of the object the display configuration is associated with.</param>
    /// <param name="configType">The type of display configuration template to use for the insertion.</param>
    /// <param name="configHospital">The optional hospital identifier used to scope the configuration; may be null when the configuration is not hospital-specific.</param>
    /// <returns>A task that represents the asynchronous operation, containing the inserted <see cref="DisplayConfig"/>, or null if the configuration could not be created.</returns>
    Task<DisplayConfig?> InsertOneWithTemplate(string objectId,
            DisplayConfigEnums.DisplayType configType, string? configHospital);

    /// <summary>
    /// Updates the card configuration based on the provided settings.
    /// </summary>
    /// <param name="baseConfig">The card configuration to be updated.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a boolean value indicating whether the update was successful.</returns>
    Task<bool> UpdateCardConfig(CardConfig baseConfig);
    /// <summary>
    /// Inserts a new card configuration using the supplied data and returns the resulting <see cref="CardConfig"/>, or null if no card config is created.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The DTO containing the data used to create the display config card.</param>
    /// <returns>A task that resolves to the inserted <see cref="CardConfig"/>, or null if the insert did not produce a card config.</returns>
    Task<CardConfig?> InsertCardConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto);
    /// <summary>
    /// Asynchronously retrieves all card configurations.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of all <see cref="CardConfig"/> items.</returns>
    Task<List<CardConfig>> GetCardConfigAll();
    /// <summary>
    /// Retrieves the card configuration associated with the specified identifier.
    /// Returns <c>null</c> when no matching card configuration is found.
    /// </summary>
    /// <param name="id">The unique identifier of the card configuration to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="CardConfig"/> if found; otherwise, <c>null</c>.</returns>
    Task<CardConfig?> GetCardConfigById(ObjectId id);
    /// <summary>
    /// Asynchronously updates the card details configuration based on the provided base configuration.
    /// </summary>
    /// <param name="baseConfig">The base card details configuration to apply during the update.</param>
    /// <returns>A task that represents the asynchronous operation, containing a boolean value indicating whether the update was successful.</returns>
    Task<bool> UpdateDetailConfig(CardDetailsConfig baseConfig);
    /// <summary>
    /// Inserts a new card detail configuration based on the provided display config data.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The DTO containing the data required to create the card detail configuration.</param>
    /// <returns>A task that resolves to the created <see cref="CardDetailsConfig"/>, or <c>null</c> if the configuration could not be inserted.</returns>
    Task<CardDetailsConfig?> InsertCardDetailConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto);
    /// <summary>
    /// Inserts a new chart configuration based on the provided display config card data.
    /// </summary>
    /// <param name="updateDisplayConfigNameDto">The data transfer object containing the details of the chart configuration to create.</param>
    /// <returns>A task that represents the asynchronous operation, containing the newly inserted <see cref="ChartConfig"/>, or <c>null</c> if the insertion was not successful.</returns>
    Task<ChartConfig?> InsertChartConfig(CreateDisplayConfigCardDto updateDisplayConfigNameDto);
    /// <summary>
    /// Asynchronously updates the chart configuration based on the provided base configuration and returns a value indicating whether the update was successful.
    /// </summary>
    /// <param name="baseConfig">The base chart configuration to apply during the update.</param>
    /// <returns>A task that represents the asynchronous operation. The result is <c>true</c> if the chart configuration was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateChartConfig(ChartConfig baseConfig);
    /// <summary>
    /// Asynchronously deletes a chart configuration identified by the specified configuration display identifier.
    /// </summary>
    /// <param name="objectIdConfigDisplay">The <see cref="ObjectId"/> of the chart configuration display to delete.</param>
    /// <returns>A task that represents the asynchronous delete operation, containing a value indicating whether the deletion was successful.</returns>
    Task<bool> DeleteChartConfig(ObjectId objectIdConfigDisplay);
    /// <summary>
    /// Asynchronously retrieves the chart configuration associated with the specified chart identifier.
    /// </summary>
    /// <param name="objectIdConfigChart">The unique identifier of the chart whose configuration should be fetched.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="ChartConfig"/> associated with the provided identifier, or <c>null</c> if no configuration is found.</returns>
    Task<ChartConfig?> GetChartConfig(ObjectId objectIdConfigChart);
}