using adas_core.Application.Exceptions; using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.Filter; using adas_core.Domain.Models.MongoModels; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using Serilog; using System.Text.RegularExpressions; namespace adas_core.Infrastructure.Repositories; /// /// Repository implementation for managing entities in MongoDB. /// Provides CRUD operations and query capabilities specific to light beacons. /// public class LightBeaconRepository : MongoRepository, ILightBeaconRepository { private readonly ApiSettings _apiSettings; /// /// Initializes a new instance of the class. /// /// The MongoDB database instance used to access the collection. /// The application API settings containing configuration values, including the collection name. public LightBeaconRepository(IMongoDatabase database, IOptions apiSettings) : base(database) { _apiSettings = apiSettings.Value; } /// /// Gets the name of the MongoDB collection used to store light beacons. /// /// The collection name retrieved from the API settings. public override string GetCollectionName() { return _apiSettings.LightBeacons; } /// /// Retrieves a list of light beacons whose identifiers are contained in the provided list of configuration relay identifiers. /// /// A list of values representing the relay identifiers to filter by. /// A containing the matching light beacons. Returns an empty list if no matches are found. public List GetLightBeaconInList(List configurationRelayList) { var filterBuilder = Builders.Filter; var filter = filterBuilder.And( filterBuilder.In(r => r.Id, configurationRelayList)); return Collection.Find(filter).ToList(); } /// /// Asynchronously retrieves a light beacon by its unique identifier. /// /// The of the relay (light beacon) to retrieve. /// /// A representing the asynchronous operation. /// The task result contains the if found; otherwise, . /// public async Task GetById(ObjectId relayId) { try { var filter = Builders.Filter.Eq(x => x.Id, relayId); var result = await Collection.FindAsync(filter, null); return result.FirstOrDefault(); } catch (Exception e) { Log.Error("Exception trying to get relay by id: {id}. Exception {e}", relayId, e); return null; } } /// /// Asynchronously retrieves a light beacon by its name. /// /// The name of the relay (light beacon) to search for. Can be . /// /// A representing the asynchronous operation. /// The task result contains the if found; otherwise, . /// public async Task GetByName(string? requestRelayName) { var filterBuilder = Builders.Filter; var filter = filterBuilder.Eq(r => r.Name, requestRelayName); return await Collection.Find(filter).FirstOrDefaultAsync(); } /// /// Asynchronously inserts a new light beacon into the database and returns the inserted entity. /// /// The instance to insert. /// /// A representing the asynchronous operation. /// The task result contains the inserted if successful; otherwise, if the operation fails. /// public async Task InsertOneAsyncAndReturn(LightBeacon beacon) { try { await Collection.InsertOneAsync(beacon); return beacon; } catch (Exception ex) { Log.Error(ex.Message); return null; } } /// /// Retrieves a paginated, sorted, and filtered set of light beacons based on the provided pagination filter. /// Results are sorted ascending by name. When a text filter is provided, a case-insensitive regex match is performed on the name field. /// /// The containing pagination and filtering criteria. /// /// An instance that can be used to further refine and execute the query. /// /// Thrown when the text filter exceeds 100 characters in length. public IFindFluent GetPaginatedRelays(PaginationFilter filter) { var filterBuilder = Builders.Filter; var sort = Builders.Sort.Ascending("name"); var filters = new List>(); if (filter.FilteredRequest == null) return CreateFindFluent(filters, sort); if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.Text)) { var textFilter = filter.FilteredRequest.Text; if (textFilter.Length > 100) throw new BadRequestException("Text filter too long"); var textFilterEscaped = Regex.Escape(textFilter); filters.Add( filterBuilder.Regex( p => p.Name, new BsonRegularExpression(textFilterEscaped, "i") ) ); } return CreateFindFluent(filters, sort); } /// /// Searches for light beacons whose name matches the specified text. /// /// The text to search for within light beacon names. /// /// A representing the asynchronous operation, /// containing a list of matching objects. /// /// This method is not yet implemented. public Task> GetSearchByName(string textToSearch) { throw new NotImplementedException(); } /// /// Creates an instance by combining the provided filter definitions /// and applying the specified sort order. If no filters are provided, an empty filter is used. /// /// A list of to be combined into the query. /// The defining the sort order of the results. /// An instance representing the constructed query. private IFindFluent CreateFindFluent(List> filters, SortDefinition sort) { var combinedFilter = filters.Any() ? Builders.Filter.And(filters) : Builders.Filter.Empty; return Collection.Find(combinedFilter).Sort(sort); } }