using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using LittleShop.Services; using LittleShop.DTOs; using System.Security.Claims; namespace LittleShop.Controllers; [ApiController] [Route("api/[controller]")] public class ReviewsController : ControllerBase { private readonly IReviewService _reviewService; private readonly ILogger _logger; public ReviewsController(IReviewService reviewService, ILogger logger) { _reviewService = reviewService; _logger = logger; } /// /// Get reviews for a specific product (public - approved reviews only) /// [HttpGet("product/{productId}")] public async Task>> GetProductReviews(Guid productId) { try { var reviews = await _reviewService.GetReviewsByProductAsync(productId, approvedOnly: true); return Ok(reviews); } catch (Exception ex) { _logger.LogError(ex, "Error getting reviews for product {ProductId}", productId); return StatusCode(500, new { Error = "Error retrieving product reviews" }); } } /// /// Get review summary statistics for a product (public) /// [HttpGet("product/{productId}/summary")] public async Task> GetProductReviewSummary(Guid productId) { try { var summary = await _reviewService.GetProductReviewSummaryAsync(productId); if (summary == null) { return NotFound(new { Error = "Product not found" }); } return Ok(summary); } catch (Exception ex) { _logger.LogError(ex, "Error getting review summary for product {ProductId}", productId); return StatusCode(500, new { Error = "Error retrieving review summary" }); } } /// /// Check if customer can review a product (public) /// [HttpGet("eligibility/customer/{customerId}/product/{productId}")] public async Task> CheckReviewEligibility(Guid customerId, Guid productId) { try { var eligibility = await _reviewService.CheckReviewEligibilityAsync(customerId, productId); return Ok(eligibility); } catch (Exception ex) { _logger.LogError(ex, "Error checking review eligibility for customer {CustomerId} and product {ProductId}", customerId, productId); return StatusCode(500, new { Error = "Error checking review eligibility" }); } } /// /// Create a new review (public - for customers via TeleBot) /// [HttpPost] public async Task> CreateReview([FromBody] CreateReviewDto createReviewDto) { try { var review = await _reviewService.CreateReviewAsync(createReviewDto); return CreatedAtAction(nameof(GetReview), new { id = review.Id }, review); } catch (InvalidOperationException ex) { return BadRequest(new { Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error creating review for product {ProductId}", createReviewDto.ProductId); return StatusCode(500, new { Error = "Error creating review" }); } } /// /// Get specific review by ID /// [HttpGet("{id}")] public async Task> GetReview(Guid id) { try { var review = await _reviewService.GetReviewByIdAsync(id); if (review == null) { return NotFound(new { Error = "Review not found" }); } return Ok(review); } catch (Exception ex) { _logger.LogError(ex, "Error getting review {ReviewId}", id); return StatusCode(500, new { Error = "Error retrieving review" }); } } /// /// Get customer's reviews (public - for TeleBot) /// [HttpGet("customer/{customerId}")] public async Task>> GetCustomerReviews(Guid customerId) { try { var reviews = await _reviewService.GetReviewsByCustomerAsync(customerId); return Ok(reviews); } catch (Exception ex) { _logger.LogError(ex, "Error getting reviews for customer {CustomerId}", customerId); return StatusCode(500, new { Error = "Error retrieving customer reviews" }); } } /// /// Get pending reviews for admin approval /// [HttpGet("pending")] [Authorize(AuthenticationSchemes = "Bearer", Roles = "Admin")] public async Task>> GetPendingReviews() { try { var reviews = await _reviewService.GetPendingReviewsAsync(); return Ok(reviews); } catch (Exception ex) { _logger.LogError(ex, "Error getting pending reviews"); return StatusCode(500, new { Error = "Error retrieving pending reviews" }); } } /// /// Update a review (admin only) /// [HttpPut("{id}")] [Authorize(AuthenticationSchemes = "Bearer", Roles = "Admin")] public async Task UpdateReview(Guid id, [FromBody] UpdateReviewDto updateReviewDto) { try { var success = await _reviewService.UpdateReviewAsync(id, updateReviewDto); if (!success) { return NotFound(new { Error = "Review not found" }); } return NoContent(); } catch (Exception ex) { _logger.LogError(ex, "Error updating review {ReviewId}", id); return StatusCode(500, new { Error = "Error updating review" }); } } /// /// Approve a review (admin only) /// [HttpPost("{id}/approve")] [Authorize(AuthenticationSchemes = "Bearer", Roles = "Admin")] public async Task ApproveReview(Guid id) { try { var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (!Guid.TryParse(userIdClaim, out var userId)) { return BadRequest(new { Error = "Invalid user ID" }); } var success = await _reviewService.ApproveReviewAsync(id, userId); if (!success) { return NotFound(new { Error = "Review not found" }); } return Ok(new { Message = "Review approved successfully" }); } catch (Exception ex) { _logger.LogError(ex, "Error approving review {ReviewId}", id); return StatusCode(500, new { Error = "Error approving review" }); } } /// /// Delete a review (admin only - soft delete) /// [HttpDelete("{id}")] [Authorize(AuthenticationSchemes = "Bearer", Roles = "Admin")] public async Task DeleteReview(Guid id) { try { var success = await _reviewService.DeleteReviewAsync(id); if (!success) { return NotFound(new { Error = "Review not found" }); } return Ok(new { Message = "Review deleted successfully" }); } catch (Exception ex) { _logger.LogError(ex, "Error deleting review {ReviewId}", id); return StatusCode(500, new { Error = "Error deleting review" }); } } }