using AutoMapper;
using gehGassi.Core.Interfaces;
using gehGassi.Core.Services;
using gehGassi.Domain.Common;
using gehGassi.Dto.Walks;
using gehGassi.Dto;
using gehGassi.Web.Helper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using gehGassi.Dto.Ratings;
using gehGassi.Domain.Walks;
using gehGassi.Dto.Common;
using System.Collections.Generic;
using System;
using gehGassi.Domain.Ratings;
using gehGassi.Domain.Dogs;
using System.Text.Json;
using gehGassi.Web.Auth;
using Asp.Versioning;
namespace gehGassi.Web.Controllers.Api
{
///
/// Controller der die Verwaltung von Ratings via Api ermöglicht
///
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[ApiVersion(1)]
[Route("api/ratings")]
[Route("api/v{v:apiVersion}/ratings")]
public class ApiRatingController : ApiBaseController
{
private readonly IRatingService _ratingService;
///
/// Erstellt eine Instanz
///
/// Instanz eines IMapper
/// Instanz von LocalizationOptions
/// Instanz eines IDogOwnerService
/// Instanz eines IRatingService
public ApiRatingController(IMapper mapper, IOptions localizationOptions, IAppUserService appUserService, IRatingService ratingService) : base(mapper, localizationOptions, appUserService)
{
_ratingService = ratingService;
}
///
/// Abfrage der Ratings eines AppUsers
///
/// Id des AppUsers
/// Letztes Update oder null, wenn noch keines
/// Liste der Anfragen
[HttpGet]
[Route("GetRatingsForSync")]
public async Task GetRatingsForSync(string appUserId, DateTimeOffset? lastUpdate)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var ratings = await _ratingService.GetForSyncAppAsync(appUserId, lastUpdate);
var dtoList = Mapper.Map>(ratings);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen eines Ratings
///
/// RatingDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreateRating")]
public async Task CreateRating(RatingDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var existingRating = await _ratingService.GetAsync(model.Id);
if (existingRating == null)
{
var rating = Mapper.Map(model);
_ratingService.Add(rating);
await _ratingService.CommitAsync(User.Identity.Name);
await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType);
await _ratingService.CommitAsync(User.Identity.Name);
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(rating);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Aktualisieren eines Ratings
///
/// RatingDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("UpdateRating")]
public async Task UpdateRating(RatingDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var rating = await _ratingService.GetAsync(model.Id);
if (rating != null)
{
if (model.UpdatedAt > rating.UpdatedAt)
{
Mapper.Map(model, rating);
await _ratingService.CommitAsync(User.Identity.Name);
await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType);
await _ratingService.CommitAsync(User.Identity.Name);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Löschen eines Ratings
///
/// RatingDto
/// Id des App-Users
/// 200OK
[HttpPost]
[Route("DeleteRating")]
public async Task DeleteRating(RatingDto model, [FromQuery] string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var rating = await _ratingService.GetAsync(model.Id);
if (rating != null)
{
var appUser = await AppUserService.GetAsync(appUserId);
if (appUser != null)
{
if (rating.FromId == appUser.Id)
{
//TODO: Löschen von verbundenen Daten!
_ratingService.Remove(rating);
await _ratingService.CommitAsync(User.Identity.Name);
await _ratingService.UpdateRatingStatisticsAsync(rating.TargetId, rating.TargetType);
await _ratingService.CommitAsync(User.Identity.Name);
return Ok();
}
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt ein Rating basierend auf Abfragekriterien zurück
///
/// RatingCheckQueryDto
/// HTTP 200 OK BOOL, Felher sonst
[HttpPost]
[Route("GetRatingEx")]
public async Task GetRatingEx(RatingCheckQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var rating = await _ratingService.GetRatingExAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType);
if (rating != null)
{
var ratingDto = Mapper.Map(rating);
return Ok(ratingDto);
}
else
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Prüft ob eine Bewertung bereits stattgefunden hat
///
/// RatingCheckQueryDto
/// HTTP 200 OK BOOL, Felher sonst
[HttpPost]
[Route("HasRated")]
public async Task HasRated(RatingCheckQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var hasRated = await _ratingService.HasRatedAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType);
return Ok(hasRated);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Prüft ob eine Bewertung vorgenommen werden darf
///
/// RatingCheckQueryDto
/// HTTP 200 OK BOOL, Felher sonst
[HttpPost]
[Route("CanRate")]
public async Task CanRate(RatingCheckQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var hasRated = await _ratingService.CanRateAsync(model.FromId, (AppUserType)model.FromType, model.TargetId, (RatingTarget)model.TargetType);
return Ok(hasRated);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfragen von Ratings
///
/// Abfragemodel
/// Liste von Ratings
[HttpPost]
[Route("GetRatings")]
public async Task GetRatings(RatingsQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
//var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var appUserId = User.AppUserId();
var queryResult = await _ratingService.GetWithNamesExAsync(appUserId, model.FromId, (AppUserType?)model.FromType, model.TargetId, (RatingTarget?)model.TargetType, sortList, model.Skip, model.Take);
response.Total = queryResult.total;
var resultList = queryResult.list;
var dtoList = Mapper.Map>(resultList);
foreach (var dtoItem in dtoList)
{
if(!string.IsNullOrWhiteSpace(dtoItem.FromPhoto))
dtoItem.FromPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.FromPhoto}";
if(!string.IsNullOrWhiteSpace(dtoItem.TargetPhoto))
dtoItem.TargetPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.TargetPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt ein Rating anhand der Id zurück
///
/// Id der Bewertung
/// 200 OK - Rating wenn gefunden, NOTFOUND sonst
[HttpGet]
[Route("GetRating")]
public async Task GetRating(string ratingId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var rating = await _ratingService.GetWithNamesAsync(ratingId);
if (rating != null)
{
var ratingDto = Mapper.Map(rating);
if (!string.IsNullOrWhiteSpace(ratingDto.FromPhoto))
ratingDto.FromPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{ratingDto.FromPhoto}";
if (!string.IsNullOrWhiteSpace(ratingDto.TargetPhoto))
ratingDto.TargetPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{ratingDto.TargetPhoto}";
return Ok(ratingDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
}
}