using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using Microsoft.Extensions.Options;
namespace adas_core.Application.Services;
///
/// Provides a proof-of-concept implementation of the IPoCMappingService interface,
/// delivering the mapping functionality defined by that contract.
///
public class PoCMappingService : IPoCMappingService
{
private readonly string _key;
private readonly bool _mappingRequired;
private readonly IPoCMappingRepository _pocMappingRepository;
private readonly int? _refreshTimeout;
private PoCMapping? _mapping;
private DateTime _nextRefresh = DateTime.MinValue;
public PoCMappingService(IPoCMappingRepository pocMappingRepository, IOptions apiSettings)
{
_pocMappingRepository = pocMappingRepository;
_refreshTimeout = apiSettings.Value.PointOfCareMapping?.Refresh;
_mappingRequired = apiSettings.Value.PointOfCareMapping?.Required ?? _mappingRequired;
_key = apiSettings.Value.PointOfCareMapping?.Key ?? "PV1";
}
///
/// Maps a received location with bed and pointOfCare to the equivalence in the PocMapping table if it finds the value,
/// otherwise it returns null
///
/// location
/// mapped location
public async Task Map(PatientLocation original)
{
var pocMapping = await GetMapping();
var poc = pocMapping?.PointOfCares.FindAll(p => p.OriginalPoC == original.UnitName);
var pocWithBed = poc?.FirstOrDefault(p => p.Beds.Any(bed => bed[0] == original.Bed));
var newBed = pocWithBed?.Beds.Where(bed => bed[0] == original.Bed).Select(bed => bed[1]).FirstOrDefault();
if (string.IsNullOrEmpty(newBed)) return _mappingRequired ? null : original;
return new PatientLocation(pocWithBed!.NewPoC, newBed);
}
///
/// Return mapping from cache of database based on refreshTime
///
///
private async Task GetMapping()
{
if (_mapping == null || DateTime.Now > _nextRefresh)
{
_mapping = await _pocMappingRepository.FindByKey(_key);
_nextRefresh = _refreshTimeout.HasValue
? DateTime.Now.AddSeconds(_refreshTimeout.Value)
: DateTime.MaxValue;
}
return _mapping;
}
}