namespace Webzine.Repository; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Webzine.EntitiesContext; using Webzine.Entity; using Webzine.Repository.Contracts; /// /// Classe qui implémente le repository pour les titres en utilisant une base de données. /// public class DbTitreRepository : ITitreRepository { private readonly ILogger logger; private readonly WebzineDbContext context; /// /// Initializes a new instance of the class. /// /// Le service de journalisation injecté pour suivre les opérations du repository. /// Le contexte de base de données injecté. public DbTitreRepository(ILogger logger, WebzineDbContext context) { this.logger = logger; this.context = context; this.logger.LogDebug(1, "NLog injecté dans DbTitreRepository"); } /// public void Add(Titre titre) { try { this.logger.LogInformation("Ajout d'un nouveau titre: {Libelle}", titre.Libelle); this.context.Titres.Add(titre); this.context.SaveChanges(); this.logger.LogDebug("Titre ajouté avec succès avec l'ID: {IdTitre}", titre.IdTitre); } catch (DbUpdateException ex) { this.logger.LogError(ex, "Erreur de base de données lors de l'ajout du titre: {Libelle}", titre.Libelle); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de l'ajout du titre: {Libelle}", titre.Libelle); throw; } } /// public int Count() { try { var count = this.context.Titres.Count(); this.logger.LogDebug("Nombre total de titres: {Count}", count); return count; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors du comptage des titres"); throw; } } /// public void Delete(Titre titre) { try { this.logger.LogInformation("Suppression du titre avec l'ID: {IdTitre}", titre.IdTitre); this.context.Titres.Remove(titre); this.context.SaveChanges(); this.logger.LogDebug("Titre supprimé avec succès: {IdTitre}", titre.IdTitre); } catch (DbUpdateException ex) { this.logger.LogError(ex, "Erreur de base de données lors de la suppression du titre ID: {IdTitre}", titre.IdTitre); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la suppression du titre ID: {IdTitre}", titre.IdTitre); throw; } } /// public IEnumerable FindTitres(int offset, int limit) { try { this.logger.LogDebug("Recherche des titres avec offset: {Offset}, limit: {Limit}", offset, limit); var titres = this.context.Titres .OrderByDescending(t => t.DateCreation) .ThenBy(t => t.Libelle) .Include(t => t.Artiste) .Include(t => t.Styles) .Paginate(offset, limit) .AsNoTracking(); return titres; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche des titres avec offset: {Offset}, limit: {Limit}", offset, limit); throw; } } /// public void IncrementNbLectures(Titre titre) { try { this.logger.LogInformation("Incrémentation du nombre de lectures pour le titre ID: {IdTitre}", titre.IdTitre); var existingTitre = this.context.Titres.Find(titre.IdTitre); if (existingTitre != null) { existingTitre.NbLectures++; this.context.SaveChanges(); this.logger.LogDebug("Nouveau nombre de lectures: {NbLectures}", existingTitre.NbLectures); } else { this.logger.LogWarning("Titre avec l'ID {IdTitre} non trouvé pour l'incrémentation des lectures", titre.IdTitre); } } catch (DbUpdateException ex) { this.logger.LogError(ex, "Erreur de base de données lors de l'incrémentation des lectures pour le titre ID: {IdTitre}", titre.IdTitre); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de l'incrémentation des lectures pour le titre ID: {IdTitre}", titre.IdTitre); throw; } } /// public void IncrementNbLikes(Titre titre) { try { this.logger.LogInformation("Incrémentation du nombre de likes pour le titre ID: {IdTitre}", titre.IdTitre); var existingTitre = this.context.Titres.Find(titre.IdTitre); if (existingTitre != null) { existingTitre.NbLikes++; this.context.SaveChanges(); this.logger.LogDebug("Nouveau nombre de likes: {NbLikes}", existingTitre.NbLikes); } else { this.logger.LogWarning("Titre avec l'ID {IdTitre} non trouvé pour l'incrémentation des likes", titre.IdTitre); } } catch (DbUpdateException ex) { this.logger.LogError(ex, "Erreur de base de données lors de l'incrémentation des likes pour le titre ID: {IdTitre}", titre.IdTitre); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de l'incrémentation des likes pour le titre ID: {IdTitre}", titre.IdTitre); throw; } } /// public void Update(Titre titre) { try { this.logger.LogInformation("Mise à jour du titre avec l'ID: {IdTitre}", titre.IdTitre); Titre existingTitre = this.Find(titre.IdTitre); if (existingTitre != null) { this.context.Entry(existingTitre).CurrentValues.SetValues(titre); // Relation many-to-many this.context.Entry(existingTitre).Collection(t => t.Styles).Load(); existingTitre.Styles.Clear(); foreach (var style in titre.Styles) { existingTitre.Styles.Add(style); } this.context.SaveChanges(); this.logger.LogDebug("Titre mis à jour avec succès: {IdTitre}", titre.IdTitre); } else { this.logger.LogWarning("Titre avec l'ID {IdTitre} non trouvé pour la mise à jour", titre.IdTitre); throw new InvalidOperationException($"Titre avec l'ID {titre.IdTitre} non trouvé."); } } catch (DbUpdateException ex) { this.logger.LogError(ex, "Erreur de base de données lors de la mise à jour du titre ID: {IdTitre}", titre.IdTitre); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la mise à jour du titre ID: {IdTitre}", titre.IdTitre); throw; } } /// public IEnumerable Search(string mot) { try { this.logger.LogInformation("Recherche des titres avec le mot-clé: {Mot}", mot); var titres = this.context.Titres .Include(t => t.Artiste) .Include(t => t.Styles) .Where(t => t.Libelle.ToLower().Contains(mot.ToLower())) .OrderBy(t => t.Libelle) .AsNoTracking(); return titres; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche des titres avec le mot-clé: {Mot}", mot); throw; } } /// public Titre Find(int idTitre) { try { this.logger.LogDebug("Recherche du titre avec l'ID: {IdTitre}", idTitre); var titre = this.context.Titres .Include(t => t.Artiste) .Include(t => t.Styles) .Include(t => t.Commentaires) .SingleOrDefault(t => t.IdTitre == idTitre); return titre; } catch (InvalidOperationException ex) { this.logger.LogWarning(ex, "Aucun titre trouvé avec l'ID: {IdTitre}", idTitre); throw; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche du titre avec l'ID: {IdTitre}", idTitre); throw; } } /// public IEnumerable FindAll() { try { var titres = this.context.Titres .Include(t => t.Artiste) .Include(t => t.Styles) .Include(t => t.Commentaires) .OrderBy(t => t.Libelle) .AsNoTracking(); this.logger.LogDebug("{Count} titres récupérés", titres.Count()); return titres; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la récupération de tous les titres"); throw; } } /// public IEnumerable SearchByStyle(string libelle) { try { this.logger.LogInformation("Recherche des titres par style: {Libelle}", libelle); var titres = this.context.Titres .Include(t => t.Artiste) .Include(t => t.Styles) .Where(t => t.Styles.Any(s => s.Libelle.ToLower() == libelle.ToLower())) .OrderBy(t => t.Libelle) .AsNoTracking(); this.logger.LogDebug("{Count} titres trouvés pour le style '{Libelle}'", titres.Count(), libelle); return titres; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche des titres par style: {Libelle}", libelle); throw; } } /// public int CountLike() { try { var likes = this.context.Titres.Sum(t => t.NbLikes); return likes; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la récupération des likes."); throw; } } /// public int CountLecture() { try { var lectures = this.context.Titres.Sum(t => t.NbLectures); return lectures; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la récupération des lectures."); throw; } } /// public string? FindMostReviewedArtistName() { try { return this.context.Titres .AsNoTracking() .GroupBy(t => new { t.IdArtiste, t.Artiste.Nom }) .OrderByDescending(g => g.Count()) .ThenBy(g => g.Key.Nom) .Select(g => g.Key.Nom) .FirstOrDefault(); } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche de l'artiste le plus chroniqué."); throw; } } /// public string? FindArtistNameWithMostReviewedAlbums() { try { return this.context.Titres .AsNoTracking() .GroupBy(t => new { t.IdArtiste, t.Artiste.Nom }) .Select(g => new { g.Key.Nom, AlbumCount = g.Select(t => t.Album).Distinct().Count(), }) .OrderByDescending(x => x.AlbumCount) .ThenBy(x => x.Nom) .Select(x => x.Nom) .FirstOrDefault(); } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche de l'artiste avec le plus d'albums chroniqués."); throw; } } /// public (int IdTitre, string Libelle)? FindMostPlayedTitle() { try { var result = this.context.Titres .AsNoTracking() .OrderByDescending(t => t.NbLectures) .ThenBy(t => t.Libelle) .Select(t => new { t.IdTitre, t.Libelle }) .FirstOrDefault(); return result == null ? null : (result.IdTitre, result.Libelle); } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recherche du titre le plus joué."); throw; } } /// public IEnumerable DerniereChronique(int offset, int limit) { try { this.logger.LogInformation("Récupération des dernières chroniques."); return this.context.Titres .AsNoTracking() .OrderByDescending(t => t.DateCreation) .Paginate(offset, limit) .Include(t => t.Artiste); } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la recuperation des dernieres chroniques."); throw; } } /// public IEnumerable TopTitre(int offset, int limit) { try { this.logger.LogInformation("Récupération du Top Titre."); var titres = this.context.Titres .AsNoTracking() .OrderByDescending(t => t.NbLikes) .Paginate(offset, limit) .Include(a => a.Artiste); return titres; } catch (Exception ex) { this.logger.LogError(ex, "Erreur lors de la récupération du Top Titre."); throw; } } }