using LiteCharms.Features.MidrandBooks.Abstractions; using LiteCharms.Features.MidrandBooks.Orders.Models; using LiteCharms.Features.MidrandBooks.Postgres; namespace LiteCharms.Features.MidrandBooks.Orders; public class OrderService(IDbContextFactory contextFactory) : IService { public async ValueTask> CreateOrderAsync(long customerId, CreateOrder request, CancellationToken cancellationToken = default) { try { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken)) return Result.Fail("Customer not found."); var order = context.Orders.Add(new Entities.Order { CustomerId = customerId, Status = OrderStatus.Pending, Total = request.TotalPrice }); return await context.SaveChangesAsync(cancellationToken) > 0 ? Result.Ok(order.Entity.Id) : Result.Fail("Failed to create order."); } catch (Exception ex) { return Result.Fail(new Error(ex.Message).CausedBy(ex)); } } public async ValueTask> AddItemToOrderAsync(long orderId, CreateOrderItem request, CancellationToken cancellationToken = default) { try { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); if (!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken)) return Result.Fail("Order not found."); if(!await context.Books.AnyAsync(ab => ab.Id == request.AuthorBookId, cancellationToken)) return Result.Fail("Author book not found."); if (!await context.Prices.AnyAsync(pp => pp.Id == request.ProductPriceId, cancellationToken)) return Result.Fail("Product price not found."); var orderItem = context.OrderItems.Add(new Entities.OrderItem { OrderId = orderId, AuthorBookId = request.AuthorBookId, ProductPriceId = request.ProductPriceId, Quantity = request.Quantity }); return await context.SaveChangesAsync(cancellationToken) > 0 ? Result.Ok(orderItem.Entity.Id) : Result.Fail("Failed to add item to order."); } catch (Exception ex) { return Result.Fail(new Error(ex.Message).CausedBy(ex)); } } public async ValueTask AddItemsToOrderAsync(long orderId, CreateOrderItem[] items, CancellationToken cancellationToken = default) { try { if(items.Length == 0) return Result.Fail("No items to add."); await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); if (!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken)) return Result.Fail("Order not found."); var existingItems = context.OrderItems.Where(oi => oi.OrderId == orderId); context.OrderItems.RemoveRange(existingItems); foreach (var item in items) { if (!await context.Books.AnyAsync(ab => ab.Id == item.AuthorBookId, cancellationToken)) return Result.Fail($"Author book with ID {item.AuthorBookId} not found."); if (!await context.Prices.AnyAsync(pp => pp.Id == item.ProductPriceId, cancellationToken)) return Result.Fail($"Product price with ID {item.ProductPriceId} not found."); context.OrderItems.Add(new Entities.OrderItem { OrderId = orderId, AuthorBookId = item.AuthorBookId, ProductPriceId = item.ProductPriceId, Quantity = item.Quantity }); } return await context.SaveChangesAsync(cancellationToken) > 0 ? Result.Ok() : Result.Fail("Failed to add items to order."); } catch (Exception ex) { return Result.Fail(new Error(ex.Message).CausedBy(ex)); } } }