using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using eprintServer.Services; using eprintServer.Requests; using eprintServer.Responses; using eprintServer.Interfaces; using eprintServer.Entities; using eprintServer.Enums; namespace eprintServer.Controllers; [ApiController] [Route("api/v1/cms/sellable-products")] [Authorize(Roles = "ADMIN,SUB_ADMIN")] public class SellableProductController : ControllerBase { private readonly ProductService _productService; private readonly IFileStorageService _fileStorageService; public SellableProductController(ProductService productService, IFileStorageService fileStorageService) { _productService = productService; _fileStorageService = fileStorageService; } [HttpGet("all-sellable-products-list")] public async Task>> GetAllProducts( [FromQuery] string? search, [FromQuery] long? categoryId, [FromQuery] SellableProductStatusEnum? status) { var products = await _productService.GetAllProductsAsync(search, categoryId, status); var response = products .Select(SellableProductResponse.FromEntity) .ToList(); return Ok(response); } [HttpGet("all-sellable-products-paginator")] public async Task>> GetPagedProducts( [FromQuery] int page = 0, [FromQuery] int size = 5, [FromQuery] string? search = null, [FromQuery] long? categoryId = null, [FromQuery] SellableProductStatusEnum? status = null, [FromQuery] decimal? lowPrice = null, [FromQuery] decimal? highPrice = null) { var pagedResult = await _productService.GetPagedProductsAsync(page, size, search, categoryId, status, lowPrice, highPrice); var responseItems = pagedResult.Items .Select(SellableProductResponse.FromEntity) .ToList(); var response = new PagedResult( responseItems, pagedResult.TotalCount, pagedResult.CurrentPage, pagedResult.PageSize); return Ok(response); } [HttpGet("sellable-product-by-id/{productId:int}")] public async Task> GetProductById(int productId) { var product = await _productService.GetProductByIdAsync(productId); if (product == null) { return NotFound($"Product with ID {productId} not found."); } return Ok(SellableProductResponse.FromEntity(product)); } [HttpPost("add")] public async Task> CreateProduct([FromBody] CreateSellableProductRequest request) { try { var product = await _productService.CreateProductAsync(request); return CreatedAtAction(nameof(GetProductById), new { productId = product.Id }, SellableProductResponse.FromEntity(product)); } catch (KeyNotFoundException knf) { // Category not found error, returning 400 Bad Request return BadRequest(knf.Message); } catch (Exception e) { return StatusCode(StatusCodes.Status500InternalServerError, $"Error creating product: {e.Message}"); } } [HttpPut("update-sellable-product/{productId:int}")] public async Task> UpdateProduct(int productId, [FromBody] UpdateSellableProductRequest request) { try { var updatedProduct = await _productService.UpdateProductAsync(productId, request); if (updatedProduct == null) { return NotFound($"Product with ID {productId} not found."); } return Ok(SellableProductResponse.FromEntity(updatedProduct)); } catch (KeyNotFoundException knf) { // New Category not found error during update, returning 400 Bad Request return BadRequest(knf.Message); } catch (Exception e) { return StatusCode(StatusCodes.Status500InternalServerError, $"Error updating product: {e.Message}"); } } [HttpDelete("delete-sellable-product/{productId:int}")] public async Task DeleteProduct(int productId) { var deleted = await _productService.DeleteProductAsync(productId); if (!deleted) { return NotFound($"Product with ID {productId} not found."); } return NoContent(); } [HttpPost("upload-product-image/{productId:int}")] public async Task> UploadProductImage(int productId, IFormFile image) { if (image == null || image.Length == 0) { return BadRequest("An image file is required."); } try { const string SubDirectory = "productImages"; var fileModel = await _fileStorageService.SaveFileAsync(image, SubDirectory); var updatedProduct = await _productService.UpdateProductImageAsync(productId, fileModel); if (updatedProduct == null) { await _fileStorageService.DeleteFileAsync(fileModel.Id); return NotFound($"Product with ID {productId} not found. Image upload failed."); } var response = new ProductImageUploadResponse(fileModel); return Ok(response); } catch (Exception ex) { return StatusCode(500, $"Something went wrong during product image upload: {ex.Message}"); } } }