using BCards.Web.Areas.Tutoriais.Models; using BCards.Web.Areas.Tutoriais.Services; using BCards.Web.Repositories; using Microsoft.AspNetCore.Mvc; namespace BCards.Web.Areas.Tutoriais.Controllers; [Area("Tutoriais")] public class TutoriaisController : Controller { private readonly IMarkdownService _markdownService; private readonly ICategoryRepository _categoryRepository; private readonly ILogger _logger; public TutoriaisController( IMarkdownService markdownService, ICategoryRepository categoryRepository, ILogger logger) { _markdownService = markdownService; _categoryRepository = categoryRepository; _logger = logger; } // GET /tutoriais public async Task Index() { var categories = await _categoryRepository.GetAllActiveAsync(); var tutoriaisPorCategoria = new Dictionary>(); foreach (var category in categories) { var artigos = await _markdownService .GetArticlesByCategoryAsync(category.Slug, "pt-BR"); if (artigos.Any()) { tutoriaisPorCategoria[category.Slug] = artigos; } } ViewBag.Categories = categories; return View(tutoriaisPorCategoria); } // GET /tutoriais/{categoria} public async Task Category(string categoria) { // Validar categoria existe var category = await _categoryRepository.GetBySlugAsync(categoria); if (category == null) { _logger.LogWarning("Categoria não encontrada: {Categoria}", categoria); return NotFound(); } var artigos = await _markdownService .GetArticlesByCategoryAsync(categoria, "pt-BR"); ViewBag.Category = category; return View(artigos); } // GET /tutoriais/{categoria}/{slug} public async Task Article(string categoria, string slug) { // Sanitização (segurança contra path traversal) categoria = categoria.Replace("..", "").Replace("/", "").Replace("\\", ""); slug = slug.Replace("..", "").Replace("/", "").Replace("\\", ""); // Validar categoria existe var category = await _categoryRepository.GetBySlugAsync(categoria); if (category == null) { _logger.LogWarning("Categoria não encontrada: {Categoria}", categoria); return NotFound(); } try { var article = await _markdownService.GetArticleAsync( $"Tutoriais/{categoria}/{slug}", "pt-BR" ); if (article == null) { _logger.LogWarning("Artigo não encontrado: {Categoria}/{Slug}", categoria, slug); return NotFound(); } // Buscar artigos relacionados da mesma categoria article.RelatedArticles = await _markdownService .GetArticlesByCategoryAsync(categoria, "pt-BR"); // Remover o artigo atual dos relacionados article.RelatedArticles = article.RelatedArticles .Where(a => a.Slug != slug) .Take(3) .ToList(); ViewBag.Category = category; return View(article); } catch (FileNotFoundException) { _logger.LogWarning("Arquivo markdown não encontrado: {Categoria}/{Slug}", categoria, slug); return NotFound(); } } }