using adas_core.Domain.Enums;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IRelayService
{
    /// <summary>
    /// Asynchronously checks the current status of the specified relay.
    /// </summary>
    /// <param name="relay">The relay whose status is being checked.</param>
    /// <returns>A task that represents the asynchronous operation, containing the current <see cref="RelayEnum.Status"/> of the relay.</returns>
    Task<RelayEnum.Status> CheckRelayStatus(Relay relay);
    /// <summary>
    /// Asynchronously checks the current status of the relay identified by the specified identifier.
    /// </summary>
    /// <param name="relayId">The unique identifier of the relay whose status is being queried.</param>
    /// <returns>A task that represents the asynchronous operation, containing the <see cref="RelayEnum.Status"/> of the requested relay.</returns>
    Task<RelayEnum.Status> CheckRelayStatus(ObjectId relayId);

    /// <summary>
    /// Powers on the specified relay.
    /// </summary>
    /// <param name="relay">The relay to power on.</param>
    Task PowerOn(Relay relay);
    /// <summary>
    /// Powers off the specified relay by sending a command to deactivate it.
    /// </summary>
    /// <param name="relay">The relay to power off.</param>
    Task PowerOff(Relay relay);
    /// <summary>
    /// Sets a manual relay with the specified status for the given point of contact and relay type.
    /// </summary>
    /// <param name="status">The status to apply to the manual relay.</param>
    /// <param name="pocId">The identifier of the point of contact associated with the relay.</param>
    /// <param name="type">The type of relay to set manually.</param>
    Task SetManualRelay(RelayEnum.Status status, ObjectId pocId, RelayEnum.Type type);
    /// <summary>
    /// Retrieves a relay by its unique identifier, returning <c>null</c> if no matching relay is found.
    /// </summary>
    /// <param name="relay">The unique identifier of the relay to look up.</param>
    /// <returns>A <see cref="Task{TResult}"/> that resolves to the <see cref="Relay"/> if found, or <c>null</c> if no relay matches the provided identifier.</returns>
    Task<Relay?> GetById(ObjectId relay);
    /// <summary>
    /// Retrieves the list of <see cref="Relay"/> objects corresponding to the specified collection of relay identifiers.
    /// </summary>
    /// <param name="relayList">The list of <see cref="ObjectId"/> values identifying the relays to retrieve. May be <c>null</c>.</param>
    /// <returns>A <see cref="List{Relay}"/> containing the relays found for the provided identifiers.</returns>
    List<Relay> GetRelayInList(List<ObjectId>? relayList);
    /// <summary>
    /// Retrieves the relays of a specified type from the provided configuration relay list.
    /// </summary>
    /// <param name="configurationRelayList">The list of relay ObjectIds to filter, or null if no configuration relays are available.</param>
    /// <param name="type">The relay type to match against the configuration relays.</param>
    /// <returns>A list of <see cref="Relay"/> objects that match the specified <paramref name="type"/>.</returns>
    List<Relay> GetRelayByTypeInList(List<ObjectId>? configurationRelayList, RelayEnum.Type type);

    /// <summary>
    /// Retrieves a paginated list of relays based on the specified pagination filter.
    /// </summary>
    /// <param name="request">The pagination filter containing the criteria used to retrieve the relays.</param>
    /// <returns>A task that represents the asynchronous operation, containing the paginated response with the requested relays.</returns>
    Task<PaginationResponse<Relay>> GetPaginatedRelays(PaginationFilter request);
    /// <summary>
    /// Inserts a new relay record based on the provided request data.
    /// </summary>
    /// <param name="request">The relay entity to be inserted.</param>
    /// <returns>A task that resolves to the inserted <see cref="Relay"/>, or <c>null</c> if the insert did not return a value.</returns>
    Task<Relay?> InsertRelay(Relay request);
    /// <summary>
    /// Updates an existing relay identified by the specified <paramref name="objectId"/> with the provided <paramref name="relay"/> data.
    /// Returns <c>null</c> when no relay is found with the given identifier.
    /// </summary>
    /// <param name="objectId">The unique identifier of the relay to update.</param>
    /// <param name="relay">The relay data containing the updated values.</param>
    /// <returns>A task that resolves to the updated <see cref="Relay"/>, or <c>null</c> if the relay was not found.</returns>
    Task<Relay?> UpdateRelayById(ObjectId objectId, Relay relay);
}