using Microsoft.EntityFrameworkCore; using LittleShop.Data; using LittleShop.Models; using LittleShop.DTOs; namespace LittleShop.Services; public interface IShippingRateService { Task> GetAllShippingRatesAsync(); Task GetShippingRateByIdAsync(Guid id); Task CreateShippingRateAsync(CreateShippingRateDto dto); Task UpdateShippingRateAsync(Guid id, UpdateShippingRateDto dto); Task DeleteShippingRateAsync(Guid id); Task CalculateShippingAsync(decimal weight, string country); } public class ShippingRateService : IShippingRateService { private readonly LittleShopContext _context; private readonly ILogger _logger; public ShippingRateService(LittleShopContext context, ILogger logger) { _context = context; _logger = logger; } public async Task> GetAllShippingRatesAsync() { var rates = await _context.ShippingRates .OrderBy(sr => sr.Country) .ToListAsync(); // Sort by MinWeight in memory to avoid SQLite decimal ordering issue return rates.OrderBy(sr => sr.MinWeight).Select(MapToDto); } public async Task GetShippingRateByIdAsync(Guid id) { var rate = await _context.ShippingRates.FindAsync(id); return rate == null ? null : MapToDto(rate); } public async Task CreateShippingRateAsync(CreateShippingRateDto dto) { var rate = new ShippingRate { Id = Guid.NewGuid(), Name = dto.Name, Description = dto.Description, Country = dto.Country, MinWeight = dto.MinWeight, MaxWeight = dto.MaxWeight, Price = dto.Price, MinDeliveryDays = dto.MinDeliveryDays, MaxDeliveryDays = dto.MaxDeliveryDays, IsActive = dto.IsActive, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; _context.ShippingRates.Add(rate); await _context.SaveChangesAsync(); _logger.LogInformation("Created shipping rate {RateId} for {Country}: {Name}", rate.Id, rate.Country, rate.Name); return MapToDto(rate); } public async Task UpdateShippingRateAsync(Guid id, UpdateShippingRateDto dto) { var rate = await _context.ShippingRates.FindAsync(id); if (rate == null) return false; rate.Name = dto.Name; rate.Description = dto.Description; rate.Country = dto.Country; rate.MinWeight = dto.MinWeight; rate.MaxWeight = dto.MaxWeight; rate.Price = dto.Price; rate.MinDeliveryDays = dto.MinDeliveryDays; rate.MaxDeliveryDays = dto.MaxDeliveryDays; rate.IsActive = dto.IsActive; rate.UpdatedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); _logger.LogInformation("Updated shipping rate {RateId}", id); return true; } public async Task DeleteShippingRateAsync(Guid id) { var rate = await _context.ShippingRates.FindAsync(id); if (rate == null) return false; _context.ShippingRates.Remove(rate); await _context.SaveChangesAsync(); _logger.LogInformation("Deleted shipping rate {RateId}", id); return true; } public async Task CalculateShippingAsync(decimal weight, string country) { // Convert weight to grams for comparison var weightInGrams = weight * 1000; // Assuming weight is in kg var rate = await _context.ShippingRates .Where(sr => sr.IsActive && sr.Country.ToLower() == country.ToLower() && sr.MinWeight <= weightInGrams && sr.MaxWeight >= weightInGrams) .OrderBy(sr => sr.Price) .FirstOrDefaultAsync(); return rate == null ? null : MapToDto(rate); } private static ShippingRateDto MapToDto(ShippingRate rate) { return new ShippingRateDto { Id = rate.Id, Name = rate.Name, Description = rate.Description, Country = rate.Country, MinWeight = rate.MinWeight, MaxWeight = rate.MaxWeight, Price = rate.Price, MinDeliveryDays = rate.MinDeliveryDays, MaxDeliveryDays = rate.MaxDeliveryDays, IsActive = rate.IsActive, CreatedAt = rate.CreatedAt, UpdatedAt = rate.UpdatedAt }; } }