CarneiroTech/Services/CaseService.cs

209 lines
6.8 KiB
C#

using CarneiroTech.Models;
using Microsoft.Extensions.Caching.Memory;
using System.Globalization;
namespace CarneiroTech.Services;
public class CaseService : ICaseService
{
private readonly IMarkdownService _markdownService;
private readonly IMemoryCache _cache;
private readonly IWebHostEnvironment _environment;
private readonly ILanguageService _languageService;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly string _casesBasePath;
private const string CACHE_KEY_PREFIX = "cases_";
private const int CACHE_MINUTES = 60;
public CaseService(IMarkdownService markdownService, IMemoryCache cache, IWebHostEnvironment environment,
ILanguageService languageService, IHttpContextAccessor httpContextAccessor)
{
_markdownService = markdownService;
_cache = cache;
_environment = environment;
_languageService = languageService;
_httpContextAccessor = httpContextAccessor;
_casesBasePath = Path.Combine(_environment.ContentRootPath, "Content", "Cases");
}
private string GetCurrentLanguage()
{
if (_httpContextAccessor.HttpContext != null)
{
return _languageService.GetCurrentLanguage(_httpContextAccessor.HttpContext);
}
return "pt"; // Default fallback
}
private string GetCasesPath(string language)
{
return Path.Combine(_casesBasePath, language);
}
public async Task<List<CaseModel>> GetAllCasesAsync()
{
var language = GetCurrentLanguage();
var cacheKey = $"{CACHE_KEY_PREFIX}{language}";
if (_cache.TryGetValue(cacheKey, out List<CaseModel>? cachedCases) && cachedCases != null)
{
return cachedCases;
}
var cases = new List<CaseModel>();
var casesPath = GetCasesPath(language);
if (!Directory.Exists(casesPath))
{
// Try Portuguese as fallback
casesPath = GetCasesPath("pt");
if (!Directory.Exists(casesPath))
{
Directory.CreateDirectory(casesPath);
return cases;
}
}
var markdownFiles = Directory.GetFiles(casesPath, "*.md");
foreach (var file in markdownFiles)
{
var caseModel = await ParseCaseFileAsync(file);
if (caseModel != null)
{
cases.Add(caseModel);
}
}
// Sort by order (ascending) and date (descending)
cases = cases.OrderBy(c => c.Metadata.Order)
.ThenByDescending(c => c.Metadata.Date)
.ToList();
_cache.Set(cacheKey, cases, TimeSpan.FromMinutes(CACHE_MINUTES));
return cases;
}
public async Task<List<CaseModel>> GetFeaturedCasesAsync()
{
var allCases = await GetAllCasesAsync();
return allCases.Where(c => c.Metadata.Featured).ToList();
}
public async Task<CaseModel?> GetCaseBySlugAsync(string slug)
{
var allCases = await GetAllCasesAsync();
return allCases.FirstOrDefault(c => c.Metadata.Slug.Equals(slug, StringComparison.OrdinalIgnoreCase));
}
public async Task<List<string>> GetAllTagsAsync()
{
var allCases = await GetAllCasesAsync();
var tags = allCases.SelectMany(c => c.Metadata.Tags)
.Distinct()
.OrderBy(t => t)
.ToList();
return tags;
}
public async Task<List<CaseModel>> GetCasesByTagAsync(string tag)
{
var allCases = await GetAllCasesAsync();
return allCases.Where(c => c.Metadata.Tags.Contains(tag, StringComparer.OrdinalIgnoreCase))
.ToList();
}
private async Task<CaseModel?> ParseCaseFileAsync(string filePath)
{
try
{
var content = await File.ReadAllTextAsync(filePath);
var frontMatter = _markdownService.ParseFrontMatter(content, out string bodyContent);
var metadata = new CaseMetadata
{
Title = GetStringValue(frontMatter, "title"),
Slug = GetStringValue(frontMatter, "slug"),
Summary = GetStringValue(frontMatter, "summary"),
Client = GetStringValue(frontMatter, "client"),
Industry = GetStringValue(frontMatter, "industry"),
Timeline = GetStringValue(frontMatter, "timeline"),
Role = GetStringValue(frontMatter, "role"),
Image = GetStringValue(frontMatter, "image"),
Tags = GetListValue(frontMatter, "tags"),
Featured = GetBoolValue(frontMatter, "featured"),
Order = GetIntValue(frontMatter, "order"),
Date = GetDateValue(frontMatter, "date"),
SeoTitle = GetStringValue(frontMatter, "seo_title"),
SeoDescription = GetStringValue(frontMatter, "seo_description"),
SeoKeywords = GetStringValue(frontMatter, "seo_keywords")
};
var htmlContent = _markdownService.ConvertToHtml(bodyContent);
return new CaseModel
{
Metadata = metadata,
ContentHtml = htmlContent,
ContentMarkdown = bodyContent
};
}
catch (Exception)
{
// Log error here if needed
return null;
}
}
private string GetStringValue(Dictionary<string, object> dict, string key)
{
return dict.ContainsKey(key) ? dict[key]?.ToString() ?? string.Empty : string.Empty;
}
private List<string> GetListValue(Dictionary<string, object> dict, string key)
{
if (!dict.ContainsKey(key)) return new List<string>();
if (dict[key] is List<object> list)
{
return list.Select(item => item?.ToString() ?? string.Empty).ToList();
}
return new List<string>();
}
private bool GetBoolValue(Dictionary<string, object> dict, string key)
{
if (!dict.ContainsKey(key)) return false;
var value = dict[key]?.ToString()?.ToLower();
return value == "true" || value == "yes" || value == "1";
}
private int GetIntValue(Dictionary<string, object> dict, string key)
{
if (!dict.ContainsKey(key)) return 0;
if (int.TryParse(dict[key]?.ToString(), out int result))
{
return result;
}
return 0;
}
private DateTime GetDateValue(Dictionary<string, object> dict, string key)
{
if (!dict.ContainsKey(key)) return DateTime.MinValue;
var dateString = dict[key]?.ToString();
if (DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result))
{
return result;
}
return DateTime.MinValue;
}
}