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 TourStorageContract(MagicCarpetDbContext dbContext, IStringLocalizer localizer) : ITourStorageContract { private readonly MagicCarpetDbContext _dbContext = dbContext; private readonly IStringLocalizer _localizer = localizer; public List GetList() { try { return [.. _dbContext.Tours.Select(x => CustomMapper.MapObject(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public List GetHistoryByTourId(string tourId) { try { return [.. _dbContext.TourHistories.Include(x => x.Tour).Where(x => x.TourId == tourId).OrderByDescending(x => x.ChangeDate).Select(x => CustomMapper.MapObject(x))]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public async Task> GetHistoriesListAsync(CancellationToken ct) { try { return [.. await _dbContext.TourHistories.Include(x => x.Tour).Select(x => CustomMapper.MapObject(x)).ToListAsync(ct)]; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public TourDataModel? GetElementById(string id) { try { return CustomMapper.MapObjectWithNull(GetTourById(id)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public TourDataModel? GetElementByName(string name) { try { return CustomMapper.MapObjectWithNull(_dbContext.Tours.FirstOrDefault(x => x.TourName == name)); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void AddElement(TourDataModel tourDataModel) { try { _dbContext.Tours.Add(CustomMapper.MapObject(tourDataModel)); _dbContext.SaveChanges(); } catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("Id", tourDataModel.Id, _localizer); } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Tours_TourName" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("TourName", tourDataModel.TourName, _localizer); } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void UpdElement(TourDataModel tourDataModel) { try { var transaction = _dbContext.Database.BeginTransaction(); try { var element = GetTourById(tourDataModel.Id) ?? throw new ElementNotFoundException(tourDataModel.Id, _localizer); if (element.Price != tourDataModel.Price) { _dbContext.TourHistories.Add(new TourHistory() { TourId = element.Id, OldPrice = element.Price }); _dbContext.SaveChanges(); } _dbContext.Tours.Update(CustomMapper.MapObject(tourDataModel, element)); _dbContext.SaveChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } } catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Tours_TourName" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("TourName", tourDataModel.TourName, _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 = GetTourById(id) ?? throw new ElementNotFoundException(id, _localizer); _dbContext.Tours.Remove(element); _dbContext.SaveChanges(); } catch (ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; } catch (Exception ex) { _dbContext.ChangeTracker.Clear(); throw new StorageException(ex, _localizer); } } public void ResElement(string id) { try { var element = GetTourById(id) ?? throw new ElementNotFoundException(id, _localizer); _dbContext.SaveChanges(); } catch { _dbContext.ChangeTracker.Clear(); throw; } } private Tour? GetTourById(string id) => _dbContext.Tours.FirstOrDefault(x => x.Id == id); }