using GhostImageManager.Data; using GhostImageManager.Models; using Microsoft.EntityFrameworkCore; namespace GhostImageManager.Services; public class ImageDatabaseService { private readonly AppDbContext _dbContext; private readonly ILogger _logger; public ImageDatabaseService(AppDbContext dbContext, ILogger logger) { _dbContext = dbContext; _logger = logger; } public async Task GetByUrlAsync(string ghostImageUrl, string instanceId) { return await _dbContext.ManagedImages .FirstOrDefaultAsync(m => m.GhostImageUrl == ghostImageUrl && m.GhostInstanceId == instanceId); } public async Task> GetByInstanceAsync(string instanceId) { return await _dbContext.ManagedImages .Where(m => m.GhostInstanceId == instanceId) .OrderBy(m => m.FileName) .ToListAsync(); } public async Task SyncImageAsync(GhostImage ghostImage, string instanceId, ExifData? exifData = null) { var existing = await GetByUrlAsync(ghostImage.Url, instanceId); var now = DateTime.UtcNow; if (existing == null) { existing = new ManagedImage { GhostImageUrl = ghostImage.Url, RelativePath = ghostImage.RelativePath, FileName = ghostImage.FileName, GhostInstanceId = instanceId, FirstSeen = now, IsOrphaned = ghostImage.IsOrphaned }; _dbContext.ManagedImages.Add(existing); _logger.LogInformation("Neues ManagedImage angelegt: {FileName}", ghostImage.FileName); } // Felder aktualisieren, die sich ändern können existing.RelativePath = ghostImage.RelativePath; existing.FileName = ghostImage.FileName; existing.FileSize = ghostImage.FileSize; existing.Width = ghostImage.Width; existing.Height = ghostImage.Height; existing.FileModifiedDate = ghostImage.LastModified; existing.IsOrphaned = ghostImage.IsOrphaned; existing.LastUpdated = now; // EXIF-Daten nur überschreiben, wenn sie vorhanden sind if (exifData != null) { if (!string.IsNullOrEmpty(exifData.CameraMake)) existing.CameraMake = exifData.CameraMake; if (!string.IsNullOrEmpty(exifData.CameraModel)) existing.CameraModel = exifData.CameraModel; if (!string.IsNullOrEmpty(exifData.Lens)) existing.Lens = exifData.Lens; if (!string.IsNullOrEmpty(exifData.Aperture)) existing.Aperture = exifData.Aperture; if (!string.IsNullOrEmpty(exifData.ShutterSpeed)) existing.ShutterSpeed = exifData.ShutterSpeed; if (!string.IsNullOrEmpty(exifData.Iso)) existing.Iso = exifData.Iso; if (!string.IsNullOrEmpty(exifData.FocalLength)) existing.FocalLength = exifData.FocalLength; if (exifData.CaptureDate.HasValue) existing.CaptureDate = exifData.CaptureDate.Value; } await _dbContext.SaveChangesAsync(); return existing; } public async Task UpdateAuthorAsync(int id, string? authorId, string? authorName) { var image = await _dbContext.ManagedImages.FindAsync(id); if (image == null) return; image.AuthorId = authorId; image.AuthorName = authorName; image.LastUpdated = DateTime.UtcNow; await _dbContext.SaveChangesAsync(); _logger.LogInformation("Autor für {FileName} aktualisiert: {AuthorName}", image.FileName, authorName); } public async Task UpdateThemeAsync(int id, string? theme) { var image = await _dbContext.ManagedImages.FindAsync(id); if (image == null) return; image.Theme = theme; image.LastUpdated = DateTime.UtcNow; await _dbContext.SaveChangesAsync(); _logger.LogInformation("Thema für {FileName} aktualisiert: {Theme}", image.FileName, theme); } public async Task UpdateCaptureDateAsync(int id, DateTime? captureDate) { var image = await _dbContext.ManagedImages.FindAsync(id); if (image == null) return; image.CaptureDate = captureDate; image.LastUpdated = DateTime.UtcNow; await _dbContext.SaveChangesAsync(); _logger.LogInformation("Aufnahmedatum für {FileName} aktualisiert: {CaptureDate}", image.FileName, captureDate); } public async Task DeleteAsync(int id) { var image = await _dbContext.ManagedImages.FindAsync(id); if (image == null) return; _dbContext.ManagedImages.Remove(image); await _dbContext.SaveChangesAsync(); _logger.LogInformation("ManagedImage gelöscht: {FileName}", image.FileName); } public async Task> SearchAsync(string instanceId, string? searchTerm = null, string? theme = null, string? authorId = null) { var query = _dbContext.ManagedImages.Where(m => m.GhostInstanceId == instanceId); if (!string.IsNullOrWhiteSpace(searchTerm)) { var term = searchTerm.ToLowerInvariant(); query = query.Where(m => (m.FileName != null && m.FileName.ToLower().Contains(term)) || (m.CameraModel != null && m.CameraModel.ToLower().Contains(term)) || (m.Theme != null && m.Theme.ToLower().Contains(term))); } if (!string.IsNullOrWhiteSpace(theme)) { query = query.Where(m => m.Theme == theme); } if (!string.IsNullOrWhiteSpace(authorId)) { query = query.Where(m => m.AuthorId == authorId); } return await query.OrderBy(m => m.FileName).ToListAsync(); } public async Task> GetThemesAsync(string instanceId) { return await _dbContext.ManagedImages .Where(m => m.GhostInstanceId == instanceId && m.Theme != null && m.Theme != "") .Select(m => m.Theme!) .Distinct() .OrderBy(t => t) .ToListAsync(); } }