using Microsoft.AspNetCore.Mvc; using QRRapidoApp.Models.ViewModels; using QRRapidoApp.Models.DTOs; using QRRapidoApp.Services; using System.Diagnostics; using System.Security.Claims; using System.Text; using System.Security.Cryptography; using Microsoft.Extensions.Localization; using QRRapidoApp.Models; using MongoDB.Driver; namespace QRRapidoApp.Controllers { [ApiController] [Route("api/[controller]")] public class QRController : ControllerBase { private readonly IQRBusinessManager _qrBusinessManager; private readonly IUserService _userService; private readonly IQRCodeService _qrService; // Mantido para Download private readonly ILogger _logger; private readonly IStringLocalizer _localizer; public QRController( IQRBusinessManager qrBusinessManager, IUserService userService, IQRCodeService qrService, ILogger logger, IStringLocalizer localizer) { _qrBusinessManager = qrBusinessManager; _userService = userService; _qrService = qrService; _logger = logger; _localizer = localizer; } [HttpPost("GenerateRapid")] public async Task GenerateRapid([FromBody] QRGenerationRequest request) { var context = new UserRequesterContext { UserId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value, IpAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown", DeviceId = Request.Cookies["_qr_device_id"] }; var result = await _qrBusinessManager.ProcessGenerationAsync(request, context); if (!result.Success) { if (result.ErrorCode == "LIMIT_REACHED") { return StatusCode(429, new { error = result.Message, upgradeUrl = "/Account/Login" }); } if (result.ErrorCode == "INSUFFICIENT_CREDITS") { return StatusCode(402, new { success = false, error = result.Message, redirectUrl = "/Pagamento/SelecaoPlano" }); } return BadRequest(new { success = false, error = result.Message }); } // Gerenciar Cookie de DeviceID para anĂ´nimos if (!context.IsAuthenticated && string.IsNullOrEmpty(context.DeviceId)) { var newDeviceId = Guid.NewGuid().ToString("N"); Response.Cookies.Append("_qr_device_id", newDeviceId, new CookieOptions { Expires = DateTime.UtcNow.AddYears(1), HttpOnly = true, Secure = true, SameSite = SameSiteMode.Strict }); } return Ok(new { success = true, QRCodeBase64 = result.QRCodeBase64, QRId = result.QRId, FromCache = result.FromCache, RemainingQRs = context.IsAuthenticated ? result.RemainingCredits : (result.RemainingFreeQRs > 0 ? result.RemainingFreeQRs : 0), Message = result.Message, GenerationTimeMs = result.GenerationTimeMs }); } [HttpGet("GetUserStats")] public async Task GetUserStats() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) return Unauthorized(); var user = await _userService.GetUserAsync(userId); if (user == null) return NotFound(); return Ok(new { credits = user.Credits, freeUsed = user.FreeQRsUsed, freeLimit = 5, isPremium = user.Credits > 0 || user.FreeQRsUsed < 5 }); } [HttpGet("Download/{qrId}")] public async Task Download(string qrId, string format = "png") { try { var qrData = await _userService.GetQRDataAsync(qrId); if (qrData == null) return NotFound(); byte[] fileContent = Convert.FromBase64String(qrData.QRCodeBase64); var contentType = "image/png"; var fileName = $"qrrapido-{qrId}.png"; if (format == "svg") { fileContent = await _qrService.ConvertToSvgAsync(qrData.QRCodeBase64); contentType = "image/svg+xml"; fileName = fileName.Replace(".png", ".svg"); } else if (format == "pdf") { fileContent = await _qrService.ConvertToPdfAsync(qrData.QRCodeBase64, qrData.Size); contentType = "application/pdf"; fileName = fileName.Replace(".png", ".pdf"); } return File(fileContent, contentType, fileName); } catch (Exception ex) { _logger.LogError(ex, "Download error"); return StatusCode(500); } } [HttpGet("History")] public async Task GetHistory(int limit = 20) { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) return Unauthorized(); return Ok(await _userService.GetUserQRHistoryAsync(userId, limit)); } [HttpPost("GenerateRapidWithLogo")] public async Task GenerateRapidWithLogo([FromForm] QRGenerationRequest request, IFormFile? logo) { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) return Unauthorized(); if (logo != null) { using var ms = new MemoryStream(); await logo.CopyToAsync(ms); request.Logo = ms.ToArray(); request.HasLogo = true; } var context = new UserRequesterContext { UserId = userId, IpAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown" }; var result = await _qrBusinessManager.ProcessGenerationAsync(request, context); if (!result.Success) return BadRequest(result); return Ok(new { success = true, QRCodeBase64 = result.QRCodeBase64, QRId = result.QRId, RemainingQRs = result.RemainingCredits }); } [HttpPost("SaveToHistory")] public async Task SaveToHistory([FromBody] SaveToHistoryRequest request) { return Ok(new { success = true }); } } public class SaveToHistoryRequest { public string QrId { get; set; } = string.Empty; } }