using System.Globalization;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Utils.Interfaces;
using Microsoft.Extensions.Options;
namespace adas_core.Domain.Utils;
///
/// Provides a sealed implementation of mapping utilities, serving as the concrete type for the contract.
///
public sealed class MappingUtils : IMappingUtils
{
private readonly List? _cccData;
private bool _isTransformedValue;
public MappingUtils(IOptions apiSettings)
{
var cccMappingData = apiSettings.Value.MappingInterventions;
_cccData = cccMappingData;
_isTransformedValue = false;
}
/*
public (string Tipo, string Nombre)? SearchByCode(double code)
{
ConvertStringToDoubleInMapping();
var data = _cccData;
foreach (var dato in data)
{
foreach (var rango in dato.Codes)
{
if (rango.FinalValue == null || rango.FinalValue.Equals("")) // Es un valor unico
{
if ((double)rango.InitialValue == code)
return (dato.Type, dato.Name);
}
else // Es un rango
{
if (code >= (double)rango.InitialValue && code <= (double)rango.FinalValue)
return (dato.Type, dato.Name);
}
}
}
return null; // No se encontro el code
}*/
public (string type, string name, string group)? SearchByCode(object code, string category)
{
// esta funcion conviete a double los string que permitan conversion si no se puede los deja como string
ConvertStringToDoubleInMapping();
var data = _cccData;
if (data == null)
return null;
// Si el parámetro es un double, buscar directamente en los valores numéricos
if (code is double searchValue)
{
foreach (var dato in data)
foreach (var rango in dato.Codes)
if (rango.FinalValue is null or "") // Es un valor unico
{
if (rango.InitialValue is double initialDouble && Math.Abs(initialDouble - searchValue) == 0 &&
category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
}
else // Es un rango
{
if (rango is { InitialValue: double initialDouble, FinalValue: double finalDouble } &&
searchValue >= initialDouble && searchValue <= finalDouble
&& category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
}
}
// Si el parámetro es un string
else if (code is string searchString)
{
// Intentar convertir el string a double para buscar entre valores numericos
if (double.TryParse(searchString, NumberStyles.Float, CultureInfo.InvariantCulture,
out var searchValueAsDouble))
{
foreach (var dato in data)
foreach (var rango in dato.Codes)
if (rango.FinalValue is null or "") // Es un valor unico
{
if (rango.InitialValue is double initialDouble &&
Math.Abs(initialDouble - searchValueAsDouble) == 0 && category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
}
else // Es un rango
{
if (rango is { InitialValue: double initialDouble, FinalValue: double finalDouble } &&
searchValueAsDouble >= initialDouble && searchValueAsDouble <= finalDouble
&& category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
}
}
else
{
// Si no es convertible a double, buscar directamente entre los valores de tipo string
foreach (var dato in data)
foreach (var rango in dato.Codes)
{
if (rango.InitialValue is string initialString && initialString == searchString &&
category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
if (rango.FinalValue is string finalString && finalString == searchString &&
category == dato.Category.ToString())
return (dato.Type, dato.Name, dato.Group)!;
}
}
}
// No se encontro el codigo
return null;
}
///
/// Retrieves a complexity value from the CCC data mapping by matching the provided .
/// If a single value entry exists for the name, its initial value is returned as an integer; if multiple ranges are defined, the value contributed by the range containing the optional is returned. Returns 0 when no matching name is found or when the data is not available.
///
/// The name of the entry to look up in the CCC data.
/// Optional weight used to select the matching range when multiple values are defined; when null, range-based lookup is skipped.
/// The matched initial value (for single-entry entries) or the contributed value (for range-based entries); returns 0 if the name is not found or no data is available.
public int GetComplexityValue(string name, double? peso = null)
{
ConvertStringToDoubleInMapping();
var data = _cccData;
if (data == null) return 0; // No encontro ningun nombre que conincida con el dado
foreach (var dato in data)
if (name.Equals(dato.Name))
{
if (dato.Value is
{
Count: 1
}) //value es una lista, si contiene un solo elemento retornaremos el initial value de ese elemento
return Convert.ToInt32(dato.Value[0].InitialValue);
if (dato.Value is { Count: > 1 } && peso != null)
foreach (var rango in dato.Value)
if (peso >= (double?)rango.InitialValue && peso <= (double?)rango.FinalValue)
return rango.ValueContributed;
}
return 0; // No encontro ningun nombre que conincida con el dado
}
///
/// Converts string representations of numeric values in the _cccData mapping to using the invariant culture, ensuring the period (".") is recognized as the decimal separator. The method only runs when the data has not already been transformed (_isTransformedValue is false) and when _cccData is not null, iterating through each mapping's Codes and Value entries to parse and replace their InitialValue and FinalValue when they are strings. After processing, it marks the transformation as completed by setting _isTransformedValue to true.
///
private void ConvertStringToDoubleInMapping()
{
// esto es para garantizar que el punto (".") sea reconocido como separador decimal
var culture = CultureInfo.InvariantCulture;
if (_isTransformedValue)
{
}
else if (_cccData != null)
{
foreach (var mapping in _cccData)
{
// Recorrer la lista Codes
foreach (var code in mapping.Codes)
{
if (code.InitialValue is string initialValueString &&
double.TryParse(initialValueString, culture, out var initialValueDouble))
code.InitialValue = initialValueDouble; // Convertir y guardar como double
if (code.FinalValue is string finalValueString &&
double.TryParse(finalValueString, culture, out var finalValueDouble))
code.FinalValue = finalValueDouble; // Convertir y guardar como double
}
// Recorrer la lista Value (si no es nula)
if (mapping.Value != null)
foreach (var value in mapping.Value)
{
if (value.InitialValue is string initialValueString &&
double.TryParse(initialValueString, culture, out var initialValueDouble))
value.InitialValue = initialValueDouble; // Convertir y guardar como double
if (value.FinalValue is string finalValueString &&
double.TryParse(finalValueString, culture, out var finalValueDouble))
value.FinalValue = finalValueDouble; // Convertir y guardar como double
}
} //Fin ford
_isTransformedValue = true;
}
}
}