using back.DataModels; using back.DTO; using back.persistance.blob; using back.services.ImageResizer; using Microsoft.EntityFrameworkCore; namespace back.context; public class PhotoContext : DbContext { private DbSet Photos { get; set; } private readonly IImageResizer _Resizer; private readonly IBlobStorageService _BlobStorage; private readonly TagContext _tagContext; private readonly EventContext _eventContext; private readonly PersonContext _personContext; public PhotoContext(DbContextOptions options, IImageResizer resizer, IBlobStorageService blobStorage, TagContext tags, EventContext events, PersonContext persons ) : base(options) { // Ensure database is created Database.EnsureCreated(); _Resizer = resizer; _BlobStorage = blobStorage; _tagContext = tags; _eventContext = events; _personContext = persons; } public async Task CreateNew(PhotoFormModel? form) { if (form == null) { return; } var photo = new PhotoModel( Guid.NewGuid().ToString(), form.Title, form.Description ?? string.Empty, string.Empty, // LowResUrl will be set later string.Empty, // MidResUrl will be set later string.Empty, // HighResUrl will be set later DateTime.UtcNow, DateTime.UtcNow, form.UserId, form.UserId ) { IsPublic = form.IsPublic }; List tasks = [ SaveBlob(photo, form), LinkTags(photo, form.Tags ?? [], form.UserId), LinkEvent(photo, form.Evento ?? "", form.UserId), LinkPersons(photo, form.People ?? [], form.UserId), ]; await Task.WhenAll(tasks); await Photos.AddAsync(photo); await SaveChangesAsync(); } private async Task LinkPersons(PhotoModel photo, string[] personas, string updatedBy = "SYSTEM") { if (photo == null || personas == null || personas.Length == 0) return; foreach (var personId in personas) { var person = await _personContext.GetById(personId); if (person != null) { await LinkPersons(photo, person, updatedBy); } } } private async Task LinkPersons(PhotoModel photo, PersonModel tag, string updatedBy = "SYSTEM") { if (tag == null) return; // Ensure the tag exists if (await _personContext.Exists(tag.Id)) { photo.Persons ??= []; photo.Persons.Add(tag); photo.UpdatedAt = DateTime.UtcNow; photo.UpdatedBy = updatedBy; // or use a more appropriate value } } private async Task LinkTags(PhotoModel photo, string[] tags, string updatedBy = "SYSTEM") { if (photo == null || tags == null || tags.Length == 0) return; foreach (var tagId in tags) { var tag = await _tagContext.GetById(tagId); if (tag != null) { await LinkTag(photo, tag, updatedBy); } } } private async Task LinkTag(PhotoModel photo, TagModel tag, string updatedBy = "SYSTEM") { if (tag == null) return; // Ensure the tag exists if (await _tagContext.Exists(tag.Id)) { photo.Tags.Add(tag); photo.UpdatedAt = DateTime.UtcNow; photo.UpdatedBy = updatedBy; // or use a more appropriate value } } private async Task LinkEvent(PhotoModel photo, string eventId, string updatedBy = "SYSTEM") { if (string.IsNullOrEmpty(eventId)) return; var evento = await _eventContext.GetById(eventId); if (evento != null) { await LinkEvent(photo, evento, updatedBy); } } private async Task LinkEvent(PhotoModel photo, EventModel? evento, string updatedBy = "SYSTEM") { if (evento == null) return; // Ensure the event exists if (await _eventContext.Exists(evento.Id)) { photo.Event = evento; photo.UpdatedAt = DateTime.UtcNow; photo.UpdatedBy = updatedBy; } } private async Task SaveBlob(PhotoModel photo, PhotoFormModel form) { if (form.Image != null && form.Image.Length > 0) { var lowRes = await _Resizer.ResizeImage(form.Image, 480); var midRes = await _Resizer.ResizeImage(form.Image, 720); // Upload images to blob storage photo.Extension = form.Image.FileName.Split('.').Last(); photo.LowResUrl = $"low/{photo.Id}.webp"; photo.MidResUrl = $"mid/{photo.Id}.webp"; photo.HighResUrl = $"high/{photo.Id}.{photo.Extension}"; await _BlobStorage.SaveAsync(lowRes, photo.LowResUrl); await _BlobStorage.SaveAsync(midRes, photo.MidResUrl); await _BlobStorage.SaveAsync(form.Image.OpenReadStream(), photo.HighResUrl); } } public async Task GetById(string id) { return await GetById(Guid.Parse(id)); } public async Task GetById(Guid id) { try { return await Photos.FindAsync(id); } catch { return null; } } public async Task GetTotalItems() { try { return await Photos.CountAsync(); } catch { return 0; } } public async Task?> GetPage(int page = 1, int pageSize = 20) { if (page < 1) page = 1; if (pageSize < 1) pageSize = 20; try { return await Photos .OrderByDescending(p => p.CreatedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); } catch { return null; } } public async Task Exists(PhotoModel? photo) { try { if (photo == null) return false; if (string.IsNullOrEmpty(photo.Id)) return false; return await Photos.AnyAsync(p => p.Id == photo.Id); } catch { return false; // Handle exceptions gracefully } } public async Task Exists(string id) { try { if (string.IsNullOrEmpty(id)) return false; return await Photos.AnyAsync(p => p.Id == id); } catch { return false; // Handle exceptions gracefully } } public async Task Delete(PhotoModel photo) { if (photo == null) return; if (await Exists(photo)) { // Delete the photo from blob storage if (!string.IsNullOrEmpty(photo.LowResUrl)) await _BlobStorage.DeleteAsync(photo.LowResUrl); if (!string.IsNullOrEmpty(photo.MidResUrl)) await _BlobStorage.DeleteAsync(photo.MidResUrl); if (!string.IsNullOrEmpty(photo.HighResUrl)) await _BlobStorage.DeleteAsync(photo.HighResUrl); Photos.Remove(photo); await SaveChangesAsync(); } } public async Task Update(PhotoModel photo) { if (photo == null) return; if (await Exists(photo)) { var evento = photo.Event; photo.Event = null; await LinkEvent(photo, evento, photo.UpdatedBy); var tags = photo.Tags.Select(t => t.Id); photo.Tags.Clear(); await LinkTags(photo, [.. tags], photo.UpdatedBy); var persons = photo.Persons?.Select(t => t.Id) ?? []; photo.Persons = null; await LinkPersons(photo, [.. persons], photo.UpdatedBy); Photos.Update(photo); await SaveChangesAsync(); } } }