using AutoMapper; using MagicCarpetContracts.DataModels; using MagicCarpetContracts.Exceptions; using MagicCarpetContracts.Mapper; using MagicCarpetContracts.Resources; using MagicCarpetContracts.StoragesContracts; using MagicCarpetDatabase.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Localization; using Npgsql; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MagicCarpetDatabase.Implementations; internal class PostStorageContract(MagicCarpetDbContext dbContext, IStringLocalizer localizer) : IPostStorageContract { private readonly MagicCarpetDbContext _dbContext = dbContext; private readonly IStringLocalizer _localizer = localizer; public List GetList() { try { return [.. _dbContext.Posts.Select(x => CustomMapper.MapObject(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 => CustomMapper.MapObject(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public PostDataModel? GetElementById(string id) { try { return CustomMapper.MapObjectWithNull(_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 CustomMapper.MapObjectWithNull(_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 { var post = MapToEntity(postDataModel); post.IsActual = true; post.ChangeDate = DateTime.UtcNow; _dbContext.Posts.Add(post); _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 = MapToEntity(postDataModel); newElement.IsActual = true; newElement.ChangeDate = DateTime.UtcNow; _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 MapToEntity(PostDataModel model) { var post = CustomMapper.MapObject(model); post.PostId = model.Id; post.Configuration = model.ConfigurationModel; return post; } private Post? GetPostById(string id) => _dbContext.Posts.Where(x => x.PostId == id) .OrderByDescending(x => x.ChangeDate).FirstOrDefault(); }