using Microsoft.AspNetCore.Mvc; using QRRapidoApp.Models; using QRRapidoApp.Services; using System.Diagnostics; using System.Security.Claims; using Microsoft.Extensions.Localization; namespace QRRapidoApp.Controllers { public class HomeController : Controller { private readonly ILogger _logger; private readonly AdDisplayService _adDisplayService; private readonly IUserService _userService; private readonly IConfiguration _config; private readonly IStringLocalizer _localizer; private readonly IMarkdownService _markdownService; public HomeController( ILogger logger, AdDisplayService adDisplayService, IUserService userService, IConfiguration config, IStringLocalizer localizer, IMarkdownService markdownService ) { _logger = logger; _adDisplayService = adDisplayService; _userService = userService; _config = config; _localizer = localizer; _markdownService = markdownService; } // Home page routes // "/" → Portuguese (canonical) // "/es-PY" → Spanish [HttpGet] [Route("/")] [Route("es-PY")] public async Task Index(string? qrType = null) { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; // Pass the requested QR type to the view to auto-select in combo ViewBag.SelectedQRType = qrType; // Set SEO Meta Tags based on QR Type if (!string.IsNullOrEmpty(qrType)) { switch (qrType.ToLower()) { case "pix": ViewBag.Title = "Gerador de Pix Grátis"; ViewBag.Description = "Crie QR Code PIX estático gratuitamente. Ideal para receber pagamentos e doações."; ViewBag.Keywords = "pix, qr code pix, gerador pix, pix estatico, receber pix"; break; case "wifi": ViewBag.Title = _localizer["WiFiQRTitle"]; ViewBag.Description = _localizer["WiFiQRDescription"]; break; case "vcard": ViewBag.Title = _localizer["VCardQRTitle"] ?? "Gerador de Cartão de Visita Digital"; ViewBag.Description = _localizer["VCardQRDescription"]; break; case "whatsapp": ViewBag.Title = "Gerador de Link WhatsApp"; ViewBag.Description = _localizer["WhatsAppQRDescription"]; break; case "email": ViewBag.Title = "Gerador de QR Code Email"; ViewBag.Description = _localizer["EmailQRDescription"]; break; case "sms": ViewBag.Title = "Gerador de QR Code SMS"; ViewBag.Description = _localizer["SMSQRDescription"]; break; case "text": ViewBag.Title = "Gerador de Texto para QR"; ViewBag.Description = _localizer["TextQRDescription"]; break; case "url": ViewBag.Title = "Gerador de URL para QR"; ViewBag.Description = _localizer["URLQRDescription"]; break; } } else { // Default SEO ViewBag.Title = _config["App:TaglinePT"]; ViewBag.Keywords = _config["SEO:KeywordsPT"]; ViewBag.Description = _localizer["QRGenerateDescription"]; } ViewBag.ShowAds = await _adDisplayService.ShouldShowAds(userId); ViewBag.IsPremium = await _adDisplayService.HasValidPremiumSubscription(userId ?? ""); ViewBag.IsAuthenticated = User?.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User?.Identity?.Name ?? ""; _adDisplayService.SetViewBagAds(ViewBag); // User stats for logged in users if (!string.IsNullOrEmpty(userId)) { ViewBag.DailyQRCount = await _userService.GetDailyQRCountAsync(userId); ViewBag.MonthlyQRCount = await _userService.GetQRCountThisMonthAsync(userId); } return View("Index"); } // Dedicated SEO Routes - Landing pages for each QR type // Portuguese (default): /pix, /wifi, etc. (no culture prefix) // Spanish: /es-PY/pix, /es-PY/wifi, etc. [Route("pix")] [Route("es-PY/pix")] public async Task Pix() => await Index("pix"); [Route("wifi")] [Route("es-PY/wifi")] public async Task Wifi() => await Index("wifi"); [Route("vcard")] [Route("es-PY/vcard")] public async Task VCard() => await Index("vcard"); [Route("whatsapp")] [Route("es-PY/whatsapp")] public async Task WhatsApp() => await Index("whatsapp"); [Route("email")] [Route("es-PY/email")] public async Task Email() => await Index("email"); [Route("sms")] [Route("es-PY/sms")] public async Task Sms() => await Index("sms"); [Route("texto")] [Route("text")] [Route("es-PY/texto")] [Route("es-PY/text")] public async Task Text() => await Index("text"); [Route("url")] [Route("es-PY/url")] public async Task UrlType() => await Index("url"); public IActionResult Privacy() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["PrivacyPolicyTitle"]; ViewBag.Description = _localizer["PrivacyPolicyDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } public IActionResult Terms() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["TermsOfUseTitle"]; ViewBag.Description = _localizer["TermsOfUseDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } public IActionResult About() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["AboutPageTitle"]; ViewBag.Description = _localizer["AboutPageDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } public IActionResult Contact() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["ContactPageTitle"]; ViewBag.Description = _localizer["ContactPageDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } public IActionResult FAQ() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["FAQPageTitle"]; ViewBag.Description = _localizer["FAQPageDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } public IActionResult HowToUse() { var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; ViewBag.ShowAds = _adDisplayService.ShouldShowAds(userId).Result; ViewBag.IsPremium = _adDisplayService.HasValidPremiumSubscription(userId ?? "").Result; ViewBag.IsAuthenticated = User.Identity?.IsAuthenticated ?? false; ViewBag.UserName = User.Identity?.Name ?? ""; ViewBag.Title = _localizer["HowToUsePageTitle"]; ViewBag.Description = _localizer["HowToUsePageDescription"]; _adDisplayService.SetViewBagAds(ViewBag); return View(); } //[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] //public IActionResult Error() //{ // return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); //} [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { var errorCode = Request.Query["code"].ToString(); var errorMessage = ""; // Interpretar c�digos de erro espec�ficos if (errorCode.StartsWith("M.C506")) { errorMessage = "Erro de autentica��o. Verifique suas credenciais e tente novamente."; } ViewBag.ErrorCode = errorCode; ViewBag.ErrorMessage = errorMessage; return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } // Dynamic QR redirect endpoint [Route("d/{id}")] public async Task DynamicRedirect(string id) { try { _adDisplayService.SetViewBagAds(ViewBag); // This would lookup the dynamic QR content from cache/database // For now, return a placeholder return Redirect("https://qrrapido.site"); } catch { return NotFound(); } } // Health check endpoint [Route("health")] public IActionResult Health() { return Ok(new { status = "healthy", timestamp = DateTime.UtcNow }); } // Sitemap endpoint for SEO [Route("sitemap.xml")] public async Task Sitemap() { var baseUrl = $"{Request.Scheme}://{Request.Host}"; var now = DateTime.UtcNow.ToString("yyyy-MM-dd"); var sitemapBuilder = new System.Text.StringBuilder(); sitemapBuilder.AppendLine(@""); sitemapBuilder.AppendLine(@""); void AppendUrl(string relativePath, string changeFreq, string priority, string? lastModOverride = null) { var normalizedPath = relativePath.StartsWith("/") ? relativePath : $"/{relativePath}"; var lastModValue = lastModOverride ?? now; sitemapBuilder.AppendLine($@" {baseUrl}{normalizedPath} {lastModValue} {changeFreq} {priority} "); } // Core entry points AppendUrl("/", "daily", "1.0"); AppendUrl("/es-PY", "daily", "0.9"); // Tools (Landing Pages) var tools = new[] { "pix", "wifi", "vcard", "whatsapp", "email", "sms", "texto", "url" }; foreach (var tool in tools) { AppendUrl($"/{tool}", "weekly", "0.9"); AppendUrl($"/es-PY/{tool}", "weekly", "0.8"); } // Informational pages var informationalPages = new[] { new { Path = "Home/About", ChangeFreq = "monthly", Priority = "0.7" }, new { Path = "Home/Contact", ChangeFreq = "monthly", Priority = "0.7" }, new { Path = "Home/FAQ", ChangeFreq = "weekly", Priority = "0.8" }, new { Path = "Home/HowToUse", ChangeFreq = "weekly", Priority = "0.8" }, new { Path = "Home/Privacy", ChangeFreq = "monthly", Priority = "0.4" }, new { Path = "Home/Terms", ChangeFreq = "monthly", Priority = "0.4" } }; foreach (var page in informationalPages) { AppendUrl($"/{page.Path}", page.ChangeFreq, page.Priority); AppendUrl($"/es-PY/{page.Path}", page.ChangeFreq, page.Priority); } // Dynamic tutorial pages from Markdown try { var allArticles = await _markdownService.GetAllArticlesForSitemapAsync(); foreach (var article in allArticles) { // Use slug from metadata or generate from title if missing var slug = !string.IsNullOrWhiteSpace(article.Slug) ? article.Slug : article.Title.ToLower().Replace(" ", "-"); // Ensure slug is only encoded once and special characters are handled var encodedSlug = slug; // Assuming slug is already URL-safe from filename var tutorialPath = article.Culture == "pt-BR" ? $"/tutoriais/{encodedSlug}" : $"/es-PY/tutoriais/{encodedSlug}"; var lastMod = article.LastMod.ToString("yyyy-MM-dd"); AppendUrl(tutorialPath, "weekly", "0.8", lastMod); } } catch (Exception ex) { _logger.LogError(ex, "Error adding tutorials to sitemap"); } sitemapBuilder.AppendLine(""); return Content(sitemapBuilder.ToString(), "application/xml", System.Text.Encoding.UTF8); } } //public class ErrorViewModel //{ // public string? RequestId { get; set; } // public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); //} }