using API.Schema;
using API.Schema.Contexts;
using API.Schema.Jobs;
using API.Schema.MangaConnectors;
using Asp.Versioning;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using static Microsoft.AspNetCore.Http.StatusCodes;
// ReSharper disable InconsistentNaming
namespace API.Controllers;
[ApiVersion(2)]
[ApiController]
[Route("v{v:apiVersion}/[controller]")]
public class SearchController(PgsqlContext context, ILog Log) : Controller
{
///
/// Initiate a search for a Manga on a specific Connector
///
///
///
///
/// MangaConnector with ID not found
/// MangaConnector with ID is disabled
/// Error during Database Operation
[HttpGet("{MangaConnectorName}/{Query}")]
[ProducesResponseType(Status200OK, "application/json")]
[ProducesResponseType(Status404NotFound)]
[ProducesResponseType(Status406NotAcceptable)]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult SearchManga(string MangaConnectorName, string Query)
{
if(context.MangaConnectors.Find(MangaConnectorName) is not { } connector)
return NotFound();
else if (connector.Enabled is false)
return StatusCode(Status406NotAcceptable);
Manga[] mangas = connector.SearchManga(Query);
List retMangas = new();
foreach (Manga manga in mangas)
{
try
{
if(AddMangaToContext(manga) is { } add)
retMangas.Add(add);
}
catch (DbUpdateException e)
{
Log.Error(e);
return StatusCode(Status500InternalServerError, e.Message);
}
}
return Ok(retMangas.ToArray());
}
///
/// Returns Manga from MangaConnector associated with URL
///
/// Manga-Page URL
///
/// Multiple connectors found for URL
/// No Manga at URL
/// No connector found for URL
/// Error during Database Operation
[HttpPost("Url")]
[ProducesResponseType(Status200OK, "application/json")]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult GetMangaFromUrl([FromBody]string url)
{
if (context.MangaConnectors.Find("Global") is not { } connector)
return StatusCode(Status500InternalServerError, "Could not find Global Connector.");
if(connector.GetMangaFromUrl(url) is not { } manga)
return BadRequest();
try
{
if(AddMangaToContext(manga) is { } add)
return Ok(add);
return StatusCode(Status500InternalServerError);
}
catch (DbUpdateException e)
{
Log.Error(e);
return StatusCode(Status500InternalServerError, e.Message);
}
}
private Manga? AddMangaToContext(Manga manga)
{
context.Mangas.Load();
context.Authors.Load();
context.Tags.Load();
context.MangaConnectors.Load();
IEnumerable mergedTags = manga.MangaTags.Select(mt =>
{
MangaTag? inDb = context.Tags.Find(mt.Tag);
return inDb ?? mt;
});
manga.MangaTags = mergedTags.ToList();
IEnumerable mergedAuthors = manga.Authors.Select(ma =>
{
Author? inDb = context.Authors.Find(ma.AuthorId);
return inDb ?? ma;
});
manga.Authors = mergedAuthors.ToList();
try
{
if (context.Mangas.Find(manga.MangaId) is { } r)
{
context.Mangas.Remove(r);
context.SaveChanges();
}
context.Mangas.Add(manga);
context.Jobs.Add(new DownloadMangaCoverJob(manga));
context.SaveChanges();
}
catch (DbUpdateException e)
{
Log.Error(e);
return null;
}
return manga;
}
}