using AutoMapper; using CatHasPawsContratcs.DataModels; using CatHasPawsContratcs.Exceptions; using CatHasPawsContratcs.Resources; using CatHasPawsContratcs.StoragesContracts; using CatHasPawsDatabase.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Localization; using Npgsql; namespace CatHasPawsDatabase.Implementations; internal class PostStorageContract : IPostStorageContract { private readonly CatHasPawsDbContext _dbContext; private readonly Mapper _mapper; private readonly IStringLocalizer _localizer; public PostStorageContract(CatHasPawsDbContext dbContext, IStringLocalizer localizer) { _dbContext = dbContext; var config = new MapperConfiguration(cfg => { cfg.CreateMap() .ForMember(x => x.Id, x => x.MapFrom(src => src.PostId)); cfg.CreateMap() .ForMember(x => x.Id, x => x.Ignore()) .ForMember(x => x.PostId, x => x.MapFrom(src => src.Id)) .ForMember(x => x.IsActual, x => x.MapFrom(src => true)) .ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow)) .ForMember(x => x.Configuration, x => x.MapFrom(src => src.ConfigurationModel)); }); _mapper = new Mapper(config); _localizer = localizer; } public List GetList() { try { return [.. _dbContext.Posts.Select(x => _mapper.Map(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public List GetPostWithHistory(string postId) { try { return [.. _dbContext.Posts.Where(x => x.PostId == postId).Select(x => _mapper.Map(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public PostDataModel? GetElementById(string id) { try { return _mapper.Map(_dbContext.Posts.FirstOrDefault(x => x.PostId == id && x.IsActual)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public PostDataModel? GetElementByName(string name) { try { return _mapper.Map(_dbContext.Posts.FirstOrDefault(x => x.PostName == name && x.IsActual)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void AddElement(PostDataModel postDataModel) { try { _dbContext.Posts.Add(_mapper.Map(postDataModel)); _dbContext.SaveChanges(); } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("PostName", postDataModel.PostName, _localizer); } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostId_IsActual" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("PostId", postDataModel.Id, _localizer); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void UpdElement(PostDataModel postDataModel) { try { var transaction = _dbContext.Database.BeginTransaction(); try { var element = GetPostById(postDataModel.Id) ?? throw new ElementNotFoundException(postDataModel.Id, _localizer); if (!element.IsActual) { throw new ElementDeletedException(postDataModel.Id, _localizer); } element.IsActual = false; _dbContext.SaveChanges(); var newElement = _mapper.Map(postDataModel); _dbContext.Posts.Add(newElement); _dbContext.SaveChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("PostName", postDataModel.PostName, _localizer); } catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void DelElement(string id) { try { var element = GetPostById(id) ?? throw new ElementNotFoundException(id, _localizer); if (!element.IsActual) { throw new ElementDeletedException(id, _localizer); } element.IsActual = false; _dbContext.SaveChanges(); } catch { _dbContext.ChangeTracker.Clear(); throw; } } public void ResElement(string id) { try { var element = GetPostById(id) ?? throw new ElementNotFoundException(id, _localizer); element.IsActual = true; _dbContext.SaveChanges(); } catch { _dbContext.ChangeTracker.Clear(); throw; } } private Post? GetPostById(string id) => _dbContext.Posts.Where(x => x.PostId == id).OrderByDescending(x => x.ChangeDate).FirstOrDefault(); }