using Microsoft.AspNetCore.Mvc; using GrossesMitainesAPI.Models; using System.Linq; using GrossesMitainesAPI.Data; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using GrossesMitainesAPI.Services; using System.Collections.Immutable; namespace GrossesMitainesAPI.Controllers; [EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]")] public class SearchController : Controller { private readonly ILogger _logger; private readonly InventoryContext _context; private readonly DatabaseCacheService _cache; private Product[]? _searchCache = null; private const int PREVIEW = 4; public SearchController(ILogger logger, InventoryContext context, DatabaseCacheService cache) { _logger = logger; _context = context; _cache = cache; if (_cache.isOk()) // Se fait une copie de la cache si elle est fonctionnelle. _searchCache = _cache.GetCacheCopy(); } [EnableCors("_myAllowSpecificOrigins"), HttpPost(Name = "Search")] public IEnumerable Post(string query, bool? preview, bool? deep) { if (_searchCache is not null) return SearchCached(query, preview, deep); else return Search(query, preview, deep); } private List Search(string query, bool? preview, bool? deep) { List products = new(); query = query.Trim(); try { // Pour faire une liste priorisée. if (preview.HasValue && preview == true) products = _context.Products.Where(x => x.Title.Contains(query)).Take(PREVIEW).ToList(); else { if (deep.HasValue && deep == true) { List title = new(), desc = new(), cat = new(); query = query.ToLower(); foreach (Product prod in _context.Products.ToList()) { string sTitle = prod.Title.Replace(",", " ").ToLower(), sCat = prod.Category.ToLower(), sDesc = prod.Description.Replace(".", " ").Replace(",", " ").ToLower(); if (sTitle.StartsWith(query)) products.Add(prod); else if (sTitle.Contains(" " + query + " ")) title.Add(prod); else if (sDesc.StartsWith(query) || sDesc.Contains(" " + query + " ")) desc.Add(prod); else if (sCat.Contains(query)) cat.Add(prod); } products.AddRange(title); products.AddRange(desc); products.AddRange(cat); } else { products = _context.Products.Where(x => x.Title.Contains(query)).ToList(); foreach (Product prod in _context.Products.Where(x => x.Description.Contains(query)).ToArray()) if (!products.Contains(prod)) products.Add(prod); foreach (Product prod in _context.Products.Where(x => x.Category.Contains(query)).ToArray()) if (!products.Contains(prod)) products.Add(prod); } } } catch (Exception e) { _logger.LogError(8, e.Message); } return products; } private List SearchCached(string query, bool? preview, bool? deep) { List products = new(); query = query.Trim(); if (_searchCache is null) { _logger.LogError(8, "Erreur de cache."); return Search(query, preview, deep); // Fallback vers version non-cached en cas d'erreur. } try { // Pour faire une liste priorisée. if (preview.HasValue && preview == true) products = _searchCache.Where(x => x.Title.Contains(query)).Take(PREVIEW).ToList(); else { if (deep.HasValue && deep == true) { List title = new(), desc = new(), cat = new(); query = query.ToLower(); foreach (Product prod in _searchCache) { string sTitle = prod.Title.Replace(",", " ").ToLower(), sCat = prod.Category.ToLower(), sDesc = prod.Description.Replace(".", " ").Replace(",", " ").ToLower(); if (sTitle.StartsWith(query)) products.Add(prod); else if (sTitle.Contains(" " + query + " ")) title.Add(prod); else if (sDesc.StartsWith(query) || sDesc.Contains(" " + query + " ")) desc.Add(prod); else if (sCat.Contains(query)) cat.Add(prod); } products.AddRange(title); products.AddRange(desc); products.AddRange(cat); } else { products = _searchCache.Where(x => x.Title.Contains(query)).ToList(); foreach (Product prod in _searchCache.Where(x => x.Description.Contains(query)).ToArray()) if (!products.Contains(prod)) products.Add(prod); foreach (Product prod in _searchCache.Where(x => x.Category.Contains(query)).ToArray()) if (!products.Contains(prod)) products.Add(prod); } } } catch (Exception e) { _logger.LogError(8, e.Message); return Search(query, preview, deep); // Fallback vers version non-cached en cas d'erreur. } return products; } }