using AutoMapper; using Microsoft.EntityFrameworkCore; using Npgsql; using SquirrelContract.DataModels; using SquirrelContract.Exceptions; using SquirrelContract.StoragesContracts; using SquirrelDatabase.Models; namespace SquirrelDatabase.Implementations; public class CocktailStorageContract : ICocktailStorageContract { private readonly SquirrelDbContext _dbContext; private readonly Mapper _mapper; public CocktailStorageContract(SquirrelDbContext dbContext) { _dbContext = dbContext; var config = new MapperConfiguration(cfg => { cfg.CreateMap(); cfg.CreateMap(); cfg.CreateMap(); }); _mapper = new Mapper(config); } public List GetList() { try { return [.. _dbContext.Cocktails.Select(x => _mapper.Map(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public List GetHistoryByCocktailId(string cocktailId) { try { return [.. _dbContext.CocktailHistories.Include(x => x.Cocktail).Where(x => x.CocktailId == cocktailId).OrderByDescending(x => x.ChangeDate).Select(x => _mapper.Map(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public CocktailDataModel? GetElementById(string id) { try { return _mapper.Map(GetCocktailById(id)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public CocktailDataModel? GetElementByName(string name) { try { return _mapper.Map(_dbContext.Cocktails.FirstOrDefault(x => x.CocktailName == name)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public void AddElement(CocktailDataModel cocktailDataModel) { try { _dbContext.Cocktails.Add(_mapper.Map(cocktailDataModel)); _dbContext.SaveChanges(); } catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("Id", cocktailDataModel.Id); } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Cocktails_CocktailName" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("CocktailName", cocktailDataModel.CocktailName); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public void UpdElement(CocktailDataModel cocktailDataModel) { try { var transaction = _dbContext.Database.BeginTransaction(); try { var element = GetCocktailById(cocktailDataModel.Id) ?? throw new ElementNotFoundException(cocktailDataModel.Id); if (element.Price != cocktailDataModel.Price) { _dbContext.CocktailHistories.Add(new CocktailHistory() { CocktailId = element.Id, OldPrice = element.Price }); _dbContext.SaveChanges(); } _dbContext.Cocktails.Update(_mapper.Map(cocktailDataModel, element)); _dbContext.SaveChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Cocktails_CocktailName" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("CocktailName", cocktailDataModel.CocktailName); } catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public void DelElement(string id) { try { var element = GetCocktailById(id) ?? throw new ElementNotFoundException(id); _dbContext.Cocktails.Remove(element); _dbContext.SaveChanges(); } catch (ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } public void ResElement(string id) { try { var element = GetCocktailById(id) ?? throw new ElementNotFoundException(id); _dbContext.SaveChanges(); } catch { _dbContext.ChangeTracker.Clear(); throw; } } private Cocktail? GetCocktailById(string id) => _dbContext.Cocktails.FirstOrDefault(x => x.Id == id); }