using API.Schema; using API.Schema.MangaConnectors; using Asp.Versioning; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using static Microsoft.AspNetCore.Http.StatusCodes; namespace API.Controllers; [ApiVersion(2)] [ApiController] [Produces("application/json")] [Route("v{v:apiVersion}/[controller]")] public class SearchController(PgsqlContext context) : Controller { /// /// Initiate a search for a Manga on all Connectors /// /// Name/Title of the Manga /// Array of Manga [HttpPost("{name}")] [ProducesResponseType(Status500InternalServerError)] public IActionResult SearchMangaGlobal(string name) { List<(Manga, List?, List?, List?, List?)> allManga = new(); foreach (MangaConnector contextMangaConnector in context.MangaConnectors) allManga.AddRange(contextMangaConnector.GetManga(name)); List retMangas = new(); foreach ((Manga? manga, List? authors, List? tags, List? links, List? altTitles) in allManga) { try { Manga? add = AddMangaToContext(manga, authors, tags, links, altTitles); if(add is not null) retMangas.Add(add); } catch (DbUpdateException) { return StatusCode(500, new ProblemResponse("An error occurred while processing your request.")); } } return Ok(retMangas.ToArray()); } /// /// Initiate a search for a Manga on a specific Connector /// /// Manga-Connector-ID /// Name/Title of the Manga /// Manga [HttpPost("{id}/{name}")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound)] [ProducesResponseType(Status500InternalServerError)] public IActionResult SearchManga(string id, string name) { MangaConnector? connector = context.MangaConnectors.Find(id); if (connector is null) return NotFound(new ProblemResponse("Connector not found.")); (Manga, List?, List?, List?, List?)[] mangas = connector.GetManga(name); List retMangas = new(); foreach ((Manga? manga, List? authors, List? tags, List? links, List? altTitles) in mangas) { try { Manga? add = AddMangaToContext(manga, authors, tags, links, altTitles); if(add is not null) retMangas.Add(add); } catch (DbUpdateException e) { return StatusCode(500, new ProblemResponse("An error occurred while processing your request.", e.Message)); } } return Ok(retMangas.ToArray()); } private Manga? AddMangaToContext(Manga? manga, List? authors, List? tags, List? links, List? altTitles) { if (manga is null) return null; Manga? existing = context.Manga.FirstOrDefault(m => m.MangaId == manga.MangaId); if (tags is not null) { IEnumerable mergedTags = tags.Select(mt => { MangaTag? inDb = context.Tags.FirstOrDefault(t => t.Equals(mt)); return inDb ?? mt; }); manga.Tags = mergedTags.ToList(); IEnumerable newTags = manga.Tags.Where(mt => !context.Tags.Any(t => t.Tag.Equals(mt.Tag))); context.Tags.AddRange(newTags); } if (authors is not null) { IEnumerable mergedAuthors = authors.Select(ma => { Author? inDb = context.Authors.FirstOrDefault(a => a.AuthorName == ma.AuthorName); return inDb ?? ma; }); manga.Authors = mergedAuthors.ToList(); IEnumerable newAuthors = manga.Authors.Where(ma => !context.Authors.Any(a => a.AuthorName == ma.AuthorName)); context.Authors.AddRange(newAuthors); } if (links is not null) { IEnumerable mergedLinks = links.Select(ml => { Link? inDb = context.Link.FirstOrDefault(l => l.LinkProvider == ml.LinkProvider && l.LinkUrl == ml.LinkUrl); return inDb ?? ml; }); manga.Links = mergedLinks.ToList(); IEnumerable newLinks = manga.Links.Where(ml => !context.Link.Any(l => l.LinkProvider == ml.LinkProvider && l.LinkUrl == ml.LinkUrl)); context.Link.AddRange(newLinks); } if (altTitles is not null) { IEnumerable mergedAltTitles = altTitles.Select(mat => { MangaAltTitle? inDb = context.AltTitles.FirstOrDefault(at => at.Language == mat.Language && at.Title == mat.Title); return inDb ?? mat; }); manga.AltTitles = mergedAltTitles.ToList(); IEnumerable newAltTitles = manga.AltTitles.Where(mat => !context.AltTitles.Any(at => at.Language == mat.Language && at.Title == mat.Title)); context.AltTitles.AddRange(newAltTitles); } existing?.UpdateWithInfo(manga); if(existing is not null) context.Manga.Update(existing); else context.Manga.Add(manga); context.SaveChanges(); return existing ?? manga; } }