package com.paymentlink.controller.api; import com.paymentlink.model.entity.Product; import com.paymentlink.reservation.ReservationService; import com.paymentlink.service.ProductService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api/cart") public class CartApiController { private final ReservationService reservationService; private final ProductService productService; public CartApiController(ReservationService reservationService, ProductService productService) { this.reservationService = reservationService; this.productService = productService; } /** * POST /api/cart/reserve - Reserve stock for cart item */ @PostMapping("/reserve") public ResponseEntity> reserveStock( @RequestHeader(value = "x-session-id", required = false) String sessionId, @RequestBody Map request) { try { if (sessionId == null || sessionId.isEmpty()) { Map error = new HashMap<>(); error.put("success", false); error.put("error", "Session ID is required"); return ResponseEntity.badRequest().body(error); } Long productId = toLong(request.get("productId")); Integer quantity = toInteger(request.get("quantity")); // Get product Product product = productService.getProductByIdRaw(productId) .orElseThrow(() -> new IllegalArgumentException("Product not found")); // Check if product has stock tracking if (product.getStock() == null) { // Unlimited stock, no reservation needed Map response = new HashMap<>(); response.put("success", true); response.put("message", "No reservation needed (unlimited stock)"); return ResponseEntity.ok(response); } // Reserve stock reservationService.reserve(sessionId, productId, quantity, product.getStock()); Map response = new HashMap<>(); response.put("success", true); response.put("message", "Stock reserved successfully"); return ResponseEntity.ok(response); } catch (IllegalStateException e) { // Insufficient stock Map error = new HashMap<>(); error.put("success", false); error.put("error", e.getMessage()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } catch (Exception e) { Map error = new HashMap<>(); error.put("success", false); error.put("error", e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); } } /** * POST /api/cart/release - Release reservation */ @PostMapping("/release") public ResponseEntity> releaseStock( @RequestHeader(value = "x-session-id", required = false) String sessionId, @RequestBody Map request) { try { if (sessionId == null || sessionId.isEmpty()) { Map error = new HashMap<>(); error.put("success", false); error.put("error", "Session ID is required"); return ResponseEntity.badRequest().body(error); } Long productId = toLong(request.get("productId")); // Release reservation reservationService.release(sessionId, productId); Map response = new HashMap<>(); response.put("success", true); response.put("message", "Reservation released successfully"); return ResponseEntity.ok(response); } catch (Exception e) { Map error = new HashMap<>(); error.put("success", false); error.put("error", e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); } } // Helper methods to safely convert Object to Long/Integer private Long toLong(Object value) { if (value == null) return null; if (value instanceof Number) { return ((Number) value).longValue(); } if (value instanceof String) { return Long.parseLong((String) value); } throw new IllegalArgumentException("Cannot convert " + value.getClass() + " to Long"); } private Integer toInteger(Object value) { if (value == null) return null; if (value instanceof Number) { return ((Number) value).intValue(); } if (value instanceof String) { return Integer.parseInt((String) value); } throw new IllegalArgumentException("Cannot convert " + value.getClass() + " to Integer"); } }