using Api.Database; using Api.Database.Entities; using Api.Extensions; using Api.Mapping; using Api.Services.Interfaces; using Common.Dtos.Common; using Common.Dtos.Season; using Common.Dtos.Specialization; using Common.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Distributed; namespace Api.Services.Implementation; public class SpecializationService(SanStudentContext context, IDistributedCache cache) : ISpecializationService, IServiceHelper { private readonly SanStudentContext _context = context; private readonly IDistributedCache _cache = cache; private List _cacheKeys = []; public async Task CreateAsync(CreateSpecializationRequest request) { try { var problems = await Validate(request); if (problems.Errors.Count > 0) { return new CreateSpecializationResponse { Ok = false, CreateSpecializationResult = string.Join(", ", problems.Errors) }; } var specialization = new Specialization() { Name = request.Name!.Trim(), ShortName = request.ShortName!.Trim() }; _context.Specializations.Add(specialization); await _context.SaveChangesAsync(); await RemoveCache(); return new CreateSpecializationResponse { Ok = true, CreateSpecializationResult = $"Zapisano nową specializację \"{specialization.Name}\"", }; } catch (Exception error) { return new CreateSpecializationResponse { Ok = false, CreateSpecializationResult = $"Błąd podczas próby zapisu specializacji: {error.Message}", }; } } public async Task GetAllAsync() { var key = "specializations"; AddKeyToCache(key); var cachedSpecs = await _cache.GetStringAsync(key); if (!string.IsNullOrEmpty(cachedSpecs)) return cachedSpecs.FromJson(); var query = _context.Specializations as IQueryable; var result = await query .OrderBy(s => s.Name) .ThenBy(s => s.ShortName) .Select(s => s.ToSpecializationDto()).ToArrayAsync(); await _cache.SetWithExpirationTimeAsync(key, result, 262487); return result; } public async Task> GetAllPagedAsync(GetSpecializationsRequest request) { var key = $"specializations_{request.PageNumber}_{request.PageSize}"; if (!string.IsNullOrWhiteSpace(request.Name)) key += $"_{request.Name.ToLower()}"; AddKeyToCache(key); var cachedSpecs = await _cache.GetStringAsync(key); if (!string.IsNullOrEmpty(cachedSpecs)) return cachedSpecs.FromJson>(); var query = _context.Specializations as IQueryable; if (!string.IsNullOrEmpty(request.Name)) query = query.Where(s => s.Name.ToLower().StartsWith(request.Name.ToLower())); var data = query .OrderBy(s => s.Name) .ThenBy(s => s.ShortName) .Select(s => s.ToSpecializationDto()); var result = await data.ToPagedListAsync(request.PageNumber, request.PageSize); await _cache.SetWithExpirationTimeAsync(key, result, 262487); return result; } public async Task Validate(CreateSpecializationRequest request) { var problems = new ValidationProblems(); if (string.IsNullOrWhiteSpace(request.Name)) problems.Errors.Add("Brak nazwy specializacji"); if (string.IsNullOrWhiteSpace(request.ShortName)) problems.Errors.Add("Brak nazwy skróconej specializacji"); if (problems.Errors.Count > 0) return problems; var specialization = await _context.Specializations .FirstOrDefaultAsync(s => s.Name.ToLower() == request.Name!.ToLower()); if (specialization is not null) problems.Errors.Add("Specializacja o podanej nazwie już istnieje"); specialization = await _context.Specializations .FirstOrDefaultAsync(s => s.ShortName.ToLower() == request.ShortName!.ToLower()); if (specialization is not null) problems.Errors.Add("Specializacja o podanej nazwie skróconej już istnieje"); return problems; } public async Task RemoveCache() { foreach (var cacheKey in _cacheKeys) await _cache.RemoveAsync(cacheKey); } public void AddKeyToCache(string key) { if (!_cacheKeys.Contains(key)) _cacheKeys.Add(key); } }