using adas_core.Application.Exceptions;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;
namespace adas_core.Application.Services;
///
/// Provides operations for retrieving and managing historical configuration changes, delegating data access to an and coordinating logging, HTTP context, and auditing concerns.
///
///
/// Implements and uses for persistence, for diagnostics, for request context, and to record local audit entries.
///
///
public class HistoricalConfigChangesService(
IHistoricalConfigChangesRepository historicalConfigChangesRepository,
ILogger logger,
IHttpContextAccessor httpContextAccessor,
ILocalAuditService auditService)
: IHistoricalConfigChangesService
{
private readonly ILogger _logger = logger;
///
/// Deletes a historical configuration change record by its identifier and creates an audit log entry recording the deletion.
///
/// The unique identifier of the historical configuration change to delete.
///
public async Task DeleteHistoricalConfigChange(ObjectId id)
{
var filter = Builders.Filter.Eq("_id", id);
var result = historicalConfigChangesRepository.FindById(id);
await historicalConfigChangesRepository.Collection.DeleteOneAsync(filter);
_logger.LogInformation("Deleted historicalConfigChanges with id: {id}", id);
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, result, null);
}
///
/// Retrieves the most recent historical configuration change entry for the specified configuration type.
///
/// The configuration type used to look up the last historical change.
/// The most recent entry, or null if no changes exist for the given type.
///
public async Task FindLastConfigChanges(DisplayConfigEnums.ConfigTypes configType)
{
var result = await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByType(configType);
return result.FirstOrDefault();
}
///
/// Retrieves a historical configuration change record by its unique identifier.
/// Returns null when no matching record is found in the repository.
///
/// The unique identifier of the historical configuration change to retrieve.
/// The matching record, or null if no record is found.
///
public async Task Get(ObjectId id)
{
return await historicalConfigChangesRepository.FindById(id);
}
///
/// Retrieves all historical configuration changes from the repository.
///
/// A task that represents the asynchronous operation, containing a collection of all records.
///
public async Task> GetAll()
{
return await historicalConfigChangesRepository.FindAll();
}
///
/// Retrieves the most recent historical configuration changes for the specified configuration type, limited to a given number of entries.
///
/// The configuration type used to filter the historical changes.
/// The maximum number of recent changes to return. Defaults to 10.
/// A collection of the latest entries matching the specified type.
///
public async Task> GetByType(DisplayConfigEnums.ConfigTypes type, int num = 10)
{
return await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByType(type, num);
}
///
/// Retrieves the most recent historical configuration changes for a given user, optionally filtered by configuration type and limited to a specified maximum number of entries.
///
/// The identifier of the user whose historical configuration changes are being retrieved.
/// Optional filter for the configuration type; when null, all configuration types are included.
/// The maximum number of historical change entries to return. Defaults to 10.
/// A task that represents the asynchronous operation, containing a collection of the user's historical configuration changes.
///
public async Task> GetByUser(string user,
DisplayConfigEnums.ConfigTypes? configTypes = null, int num = 10)
{
return await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByUser(user, configTypes, num);
}
///
/// Inserts a new historical configuration change record into the repository and creates a corresponding audit log entry.
/// If the repository returns null, a conflict exception is thrown; on failure, the error is logged and null is returned.
///
/// The historical configuration change entity to insert.
/// The inserted entity, or null if the operation fails.
/// Thrown when the repository returns null after the insert operation.
///
public async Task InsertOne(HistoricalConfigChanges historicalConfigChanges)
{
try
{
var result = await historicalConfigChangesRepository.InsertOneAsync(historicalConfigChanges) ??
throw new ConflictException(HttpEnum.ErrorMessage.ConflictCreationFailed);
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, null, result);
return await historicalConfigChangesRepository.InsertOneAsync(historicalConfigChanges);
}
catch (Exception ex)
{
_logger.LogError("Exception inserting historicalConfigChanges {changes} exception:{e} ",
historicalConfigChanges.ToJson(), ex);
return null;
}
}
///
/// Updates an existing historical configuration change record, creating an audit log entry for the change.
/// If the record is not found, a is thrown; any other exception is logged and the method returns null.
///
/// The historical configuration change entity containing the updated values to persist.
/// The updated entity on success, or null if an error occurs during the operation.
/// Thrown when no existing historical configuration change is found with the specified Id.
///
///
public async Task UpdateHistoricalConfigChange(
HistoricalConfigChanges historicalConfigChanges)
{
try
{
var oldHistorical = await historicalConfigChangesRepository.FindById(historicalConfigChanges.Id) ??
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
var result = await historicalConfigChangesRepository.Update(historicalConfigChanges);
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldHistorical, result);
return result;
}
catch (Exception ex)
{
_logger.LogError("Exception updating historicalConfigChanges {changes} exception:{e} ",
historicalConfigChanges.ToJson(), ex);
return null;
}
}
///
/// Asynchronously logs a change to a display configuration, recording the user who made the change,
/// the configuration type, the previous value, and the new value. Logs an error if the insertion fails,
/// or a debug message if it succeeds.
///
/// The username of the user who made the configuration change.
/// The type of configuration that was changed.
/// The new configuration value after the change.
/// The previous configuration value before the change.
///
public async Task LogConfigChanged(string user, DisplayConfigEnums.ConfigTypes configType, string newConfig,
string oldConfig)
{
HistoricalConfigChanges historicalConfigChanges = new()
{
ConfigType = configType,
Time = DateTime.Now,
Username = user,
OldConfig = oldConfig,
NewConfig = newConfig
};
var result = await InsertOne(historicalConfigChanges);
if (result == null)
_logger.LogError("Error logging config changes. newConfig: {newConfig}, oldConfig: {oldConfig}",
historicalConfigChanges.NewConfig, historicalConfigChanges.OldConfig);
else
_logger.LogDebug("Config changes logged. newConfig: {newConfig}, oldConfig: {oldConfig}",
historicalConfigChanges.NewConfig, historicalConfigChanges.OldConfig);
}
}