using Microsoft.EntityFrameworkCore; using CredentialManager.Data; using CredentialManager.Models; using System.Text.Json; namespace CredentialManager.Services; /// /// Implementazione del servizio per la gestione dei profili Data Coupler /// public class DataCouplerProfileService : IDataCouplerProfileService { private readonly CredentialDbContext _context; public DataCouplerProfileService(CredentialDbContext context) { _context = context; } /// /// Ottiene tutti i profili attivi /// public async Task> GetAllProfilesAsync() { return await _context.DataCouplerProfiles .Include(p => p.SourceCredential) .Include(p => p.DestinationCredential) .Where(p => p.IsActive) .OrderByDescending(p => p.LastUsedAt) .ThenByDescending(p => p.CreatedAt) .ToListAsync(); } /// /// Ottiene tutti i profili per nome (inclusi quelli inattivi) /// public async Task GetProfileByNameIncludingInactiveAsync(string name) { return await _context.DataCouplerProfiles .Include(p => p.SourceCredential) .Include(p => p.DestinationCredential) .FirstOrDefaultAsync(p => p.Name.ToLower() == name.ToLower()); } /// /// Ottiene un profilo per ID /// public async Task GetProfileByIdAsync(int id) { return await _context.DataCouplerProfiles .Include(p => p.SourceCredential) .Include(p => p.DestinationCredential) .FirstOrDefaultAsync(p => p.Id == id && p.IsActive); } /// /// Ottiene un profilo per nome /// public async Task GetProfileByNameAsync(string name) { return await _context.DataCouplerProfiles .Include(p => p.SourceCredential) .Include(p => p.DestinationCredential) .FirstOrDefaultAsync(p => p.Name == name && p.IsActive); } /// /// Salva un nuovo profilo /// public async Task SaveProfileAsync(DataCouplerProfile profile) { profile.CreatedAt = DateTime.UtcNow; profile.IsActive = true; _context.DataCouplerProfiles.Add(profile); await _context.SaveChangesAsync(); return profile; } /// /// Aggiorna un profilo esistente /// public async Task UpdateProfileAsync(DataCouplerProfile profile) { var existingProfile = await _context.DataCouplerProfiles .FirstOrDefaultAsync(p => p.Id == profile.Id); if (existingProfile == null) { throw new InvalidOperationException($"Profilo con ID {profile.Id} non trovato"); } // Aggiorna le proprietà (evita di aggiornare il nome se è uguale per evitare unique constraint) if (!string.Equals(existingProfile.Name, profile.Name, StringComparison.OrdinalIgnoreCase)) { existingProfile.Name = profile.Name; } existingProfile.Description = profile.Description; existingProfile.SourceType = profile.SourceType; existingProfile.SourceCredentialId = profile.SourceCredentialId; existingProfile.SourceSchema = profile.SourceSchema; existingProfile.SourceTable = profile.SourceTable; existingProfile.SourceFilePath = profile.SourceFilePath; existingProfile.DestinationType = profile.DestinationType; existingProfile.DestinationCredentialId = profile.DestinationCredentialId; existingProfile.DestinationSchema = profile.DestinationSchema; existingProfile.DestinationTable = profile.DestinationTable; existingProfile.DestinationEndpoint = profile.DestinationEndpoint; existingProfile.FieldMappingJson = profile.FieldMappingJson; existingProfile.SourceKeyField = profile.SourceKeyField; existingProfile.UseRecordAssociations = profile.UseRecordAssociations; existingProfile.IsActive = profile.IsActive; await _context.SaveChangesAsync(); return existingProfile; } /// /// Elimina un profilo (soft delete) /// public async Task DeleteProfileAsync(int id) { var profile = await _context.DataCouplerProfiles .FirstOrDefaultAsync(p => p.Id == id); if (profile == null) { return false; } profile.IsActive = false; await _context.SaveChangesAsync(); return true; } /// /// Aggiorna la data di ultimo utilizzo di un profilo /// public async Task UpdateLastUsedAsync(int id) { var profile = await _context.DataCouplerProfiles .FirstOrDefaultAsync(p => p.Id == id); if (profile != null) { profile.LastUsedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); } } /// /// Verifica se esiste un profilo con il nome specificato /// public async Task ProfileExistsAsync(string name, int? excludeId = null) { var query = _context.DataCouplerProfiles .Where(p => p.Name == name && p.IsActive); if (excludeId.HasValue) { query = query.Where(p => p.Id != excludeId.Value); } return await query.AnyAsync(); } /// /// Serializza la lista di mapping dei campi in JSON /// public string SerializeFieldMappings(List? mappings) { if (mappings == null || !mappings.Any()) return string.Empty; return JsonSerializer.Serialize(mappings, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } /// /// Deserializza il JSON dei mapping dei campi /// public List DeserializeFieldMappings(string? json) { if (string.IsNullOrWhiteSpace(json)) return new List(); try { return JsonSerializer.Deserialize>(json, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }) ?? new List(); } catch { return new List(); } } /// /// Converte un DataCouplerProfile in DTO /// public DataCouplerProfileDto ToDto(DataCouplerProfile profile) { return new DataCouplerProfileDto { Id = profile.Id, Name = profile.Name, Description = profile.Description, SourceType = profile.SourceType, SourceCredentialId = profile.SourceCredentialId, SourceCredentialName = profile.SourceCredential?.Name, SourceDatabaseName = profile.SourceDatabaseName, SourceSchema = profile.SourceSchema, SourceTable = profile.SourceTable, SourceFilePath = profile.SourceFilePath, DestinationType = profile.DestinationType, DestinationCredentialId = profile.DestinationCredentialId, DestinationCredentialName = profile.DestinationCredential?.Name, DestinationSchema = profile.DestinationSchema, DestinationTable = profile.DestinationTable, DestinationEndpoint = profile.DestinationEndpoint, FieldMappings = DeserializeFieldMappings(profile.FieldMappingJson), SourceKeyField = profile.SourceKeyField, UseRecordAssociations = profile.UseRecordAssociations }; } /// /// Converte un DTO in DataCouplerProfile /// public DataCouplerProfile FromDto(DataCouplerProfileDto dto, string? createdBy = null) { return new DataCouplerProfile { Id = dto.Id ?? 0, Name = dto.Name, Description = dto.Description, SourceType = dto.SourceType, SourceCredentialId = dto.SourceCredentialId, SourceDatabaseName = dto.SourceDatabaseName, SourceSchema = dto.SourceSchema, SourceTable = dto.SourceTable, SourceFilePath = dto.SourceFilePath, DestinationType = dto.DestinationType, DestinationCredentialId = dto.DestinationCredentialId, DestinationSchema = dto.DestinationSchema, DestinationTable = dto.DestinationTable, DestinationEndpoint = dto.DestinationEndpoint, FieldMappingJson = SerializeFieldMappings(dto.FieldMappings), SourceKeyField = dto.SourceKeyField, UseRecordAssociations = dto.UseRecordAssociations, CreatedBy = createdBy }; } }