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; }
}
}