using Microsoft.AspNetCore.Mvc; using QRRapidoApp.Data; using QRRapidoApp.Models; using System.Diagnostics; using System.Security.Claims; namespace QRRapidoApp.Controllers { /// /// Controller for handling user ratings /// [Route("api/ratings")] [ApiController] public class RatingsController : ControllerBase { private readonly MongoDbContext _dbContext; private readonly ILogger _logger; public RatingsController(MongoDbContext dbContext, ILogger logger) { _dbContext = dbContext; _logger = logger; } /// /// Submit a new rating /// [HttpPost] public async Task SubmitRating([FromBody] RatingSubmissionDto submission) { var stopwatch = Stopwatch.StartNew(); using (_logger.BeginScope(new Dictionary { ["Rating"] = submission.Rating, ["HasComment"] = !string.IsNullOrWhiteSpace(submission.Comment) })) { _logger.LogInformation("Rating submission - Rating: {Rating}, HasName: {HasName}, HasEmail: {HasEmail}, HasComment: {HasComment}", submission.Rating, !string.IsNullOrWhiteSpace(submission.Name), !string.IsNullOrWhiteSpace(submission.Email), !string.IsNullOrWhiteSpace(submission.Comment)); try { // Validate rating value if (submission.Rating < 1 || submission.Rating > 5) { _logger.LogWarning("Invalid rating value - Rating: {Rating}", submission.Rating); return BadRequest(new { error = "Rating must be between 1 and 5" }); } // Check MongoDB connection if (!_dbContext.IsConnected || _dbContext.Ratings == null) { _logger.LogError("MongoDB not connected or Ratings collection unavailable"); return StatusCode(503, new { error = "Database unavailable" }); } // Get user ID if authenticated var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; // Get culture from request var culture = System.Globalization.CultureInfo.CurrentUICulture.Name; // Get IP address var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString(); // Create rating object var rating = new Rating { RatingValue = submission.Rating, Name = submission.Name, Email = submission.Email, Comment = submission.Comment, Url = submission.Url ?? string.Empty, UserAgent = submission.UserAgent ?? string.Empty, UserId = userId, CreatedAt = DateTime.UtcNow, IpAddress = ipAddress, Culture = culture }; // Save to MongoDB await _dbContext.Ratings.InsertOneAsync(rating); stopwatch.Stop(); _logger.LogInformation("Rating saved successfully - RatingId: {RatingId}, Rating: {Rating}, UserId: {UserId}, ProcessingTime: {ProcessingTimeMs}ms", rating.Id, rating.RatingValue, userId ?? "anonymous", stopwatch.ElapsedMilliseconds); return Ok(new { success = true, message = "Thank you for your feedback!", ratingId = rating.Id }); } catch (Exception ex) { stopwatch.Stop(); _logger.LogError(ex, "Error saving rating - ProcessingTime: {ProcessingTimeMs}ms", stopwatch.ElapsedMilliseconds); return StatusCode(500, new { error = "Error saving rating" }); } } } } /// /// DTO for rating submission /// public class RatingSubmissionDto { public int Rating { get; set; } public string? Name { get; set; } public string? Email { get; set; } public string? Comment { get; set; } public string? Url { get; set; } public string? UserAgent { get; set; } } }