using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using QRRapidoApp.Models.ViewModels; using QRRapidoApp.Services; using System.Security.Claims; namespace QRRapidoApp.Controllers { [Authorize] public class PremiumController : Controller { private readonly StripeService _stripeService; private readonly IUserService _userService; private readonly AdDisplayService _adDisplayService; private readonly IConfiguration _config; private readonly ILogger _logger; public PremiumController(StripeService stripeService, IUserService userService, AdDisplayService adDisplayService, IConfiguration config, ILogger logger) { _stripeService = stripeService; _userService = userService; _adDisplayService = adDisplayService; _config = config; _logger = logger; } [HttpGet] public async Task Upgrade() { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return RedirectToAction("Login", "Account"); } var user = await _userService.GetUserAsync(userId); if (user?.IsPremium == true) { return RedirectToAction("Dashboard"); } var model = new UpgradeViewModel { CurrentPlan = "Free", PremiumPrice = _config.GetValue("Premium:PremiumPrice"), Features = _config.GetSection("Premium:Features").Get>() ?? new(), RemainingQRs = await _userService.GetDailyQRCountAsync(userId), IsAdFreeActive = !await _adDisplayService.ShouldShowAds(userId), DaysUntilAdExpiry = (int)((await _adDisplayService.GetAdFreeExpiryDate(userId) - DateTime.UtcNow)?.TotalDays ?? 0) }; return View(model); } [HttpPost] public async Task CreateCheckout() { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return Json(new { success = false, error = "User not authenticated" }); } var priceId = _config["Stripe:PriceId"]; if (string.IsNullOrEmpty(priceId)) { return Json(new { success = false, error = "Stripe not configured" }); } try { var checkoutUrl = await _stripeService.CreateCheckoutSessionAsync(userId, priceId); return Json(new { success = true, url = checkoutUrl }); } catch (Exception ex) { _logger.LogError(ex, $"Error creating checkout session for user {userId}"); return Json(new { success = false, error = ex.Message }); } } [HttpGet] public async Task Success(string session_id) { if (string.IsNullOrEmpty(session_id)) { return RedirectToAction("Upgrade"); } try { ViewBag.Success = true; ViewBag.SessionId = session_id; return View(); } catch (Exception ex) { _logger.LogError(ex, $"Error processing successful payment for session {session_id}"); return RedirectToAction("Upgrade"); } } [HttpGet] public IActionResult Cancel() { ViewBag.Cancelled = true; return View("Upgrade"); } [HttpPost] [AllowAnonymous] public async Task StripeWebhook() { try { using var reader = new StreamReader(HttpContext.Request.Body); var json = await reader.ReadToEndAsync(); var signature = Request.Headers["Stripe-Signature"].FirstOrDefault(); if (string.IsNullOrEmpty(signature)) { return BadRequest("Missing Stripe signature"); } await _stripeService.HandleWebhookAsync(json, signature); return Ok(); } catch (Exception ex) { _logger.LogError(ex, "Error processing Stripe webhook"); return BadRequest(ex.Message); } } [HttpGet] public async Task Dashboard() { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return RedirectToAction("Login", "Account"); } var user = await _userService.GetUserAsync(userId); if (user?.IsPremium != true) { return RedirectToAction("Upgrade"); } var model = new PremiumDashboardViewModel { User = user, QRCodesThisMonth = await _userService.GetQRCountThisMonthAsync(userId), TotalQRCodes = user.QRHistoryIds?.Count ?? 0, SubscriptionStatus = await _stripeService.GetSubscriptionStatusAsync(user.StripeSubscriptionId), RecentQRCodes = await _userService.GetUserQRHistoryAsync(userId, 10) }; // Calculate next billing date (simplified) if (user.PremiumExpiresAt.HasValue) { model.NextBillingDate = user.PremiumExpiresAt.Value.AddDays(-2); // Approximate } // QR type statistics model.QRTypeStats = model.RecentQRCodes .GroupBy(q => q.Type) .ToDictionary(g => g.Key, g => g.Count()); return View(model); } [HttpPost] public async Task CancelSubscription() { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return Json(new { success = false, error = "User not authenticated" }); } try { var user = await _userService.GetUserAsync(userId); if (user?.StripeSubscriptionId == null) { return Json(new { success = false, error = "No active subscription found" }); } var success = await _stripeService.CancelSubscriptionAsync(user.StripeSubscriptionId); if (success) { TempData["Success"] = "Assinatura cancelada com sucesso. Você manterá o acesso premium até o final do período pago."; return Json(new { success = true }); } else { return Json(new { success = false, error = "Failed to cancel subscription" }); } } catch (Exception ex) { _logger.LogError(ex, $"Error canceling subscription for user {userId}"); return Json(new { success = false, error = ex.Message }); } } [HttpGet] public async Task BillingPortal() { var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return RedirectToAction("Login", "Account"); } try { // This would create a Stripe billing portal session // For now, redirect to dashboard return RedirectToAction("Dashboard"); } catch (Exception ex) { _logger.LogError(ex, $"Error creating billing portal for user {userId}"); return RedirectToAction("Dashboard"); } } } }