using AutoMapper; using CityInfo.API.Entities; using CityInfo.API.Models; using CityInfo.API.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.JsonPatch; using Microsoft.AspNetCore.Mvc; namespace CityInfo.API.Controllers { [Route("api/cities/{cityId}/pointsofinterest/", Name = "GetPointsOfInterest")] [Authorize(Policy = "MustBeFromCharleroi")] [ApiController] public class PointsOfInterestController : ControllerBase { private readonly ILogger _logger; private readonly IMailService _mailService; private readonly ICityInfoRepository _cityInfoRepository; private readonly IMapper _mapper; public PointsOfInterestController( ILogger logger, IMailService mailService, ICityInfoRepository cityInfoRepository, IMapper mapper) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _mailService = mailService ?? throw new ArgumentNullException(nameof(mailService)); _cityInfoRepository = cityInfoRepository ?? throw new ArgumentNullException(nameof(cityInfoRepository)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); } [HttpGet] public async Task>> GetPointsOfInterest(int cityId) { //throw new Exception("pipi"); try { //throw new Exception("caca prout"); var cityName = User.Claims.FirstOrDefault(claim => claim.Type == "city")?.Value; if (!await _cityInfoRepository.CityNameMatchesCityId(cityName, cityId)) { return Forbid(); } if(!await _cityInfoRepository.CityExistAsync(cityId)) { _logger.LogInformation($"City with Id {cityId} wasn't found when accessing points of interest."); return NotFound(); } var pointsOfInterest = await _cityInfoRepository.GetPointsOfinterestForCityAsync(cityId); return Ok(_mapper.Map>(pointsOfInterest)); } catch (Exception ex) { _logger.LogCritical($"Exception while getting points of interest for city with id {cityId}", ex); return StatusCode(500, "A problem happened while handling your request."); } } [HttpGet("{pointOfInterestId}", Name = "GetPointOfInterest")] public async Task> GetPointOfInterest(int cityId, int pointOfInterestId) { if (!await _cityInfoRepository.CityExistAsync(cityId)) { _logger.LogInformation($"City with Id {cityId} wasn't found when accessing point of interest."); return NotFound(); } var pointOfInterest = await _cityInfoRepository.GetPointOfInterestForCityAsync(cityId, pointOfInterestId); if (pointOfInterest == null) { return NotFound(); } return Ok(_mapper.Map(pointOfInterest)); } [HttpPost(Name = "CreatePointOfInterest")] public async Task> CreatePointOfInterest( int cityId, PointOfInterestForCreationDto pointOfInterest) { if (!await _cityInfoRepository.CityExistAsync(cityId)) { return NotFound(); } var finalPointOfInterest = _mapper.Map(pointOfInterest); await _cityInfoRepository.CreatePointOfInterestForCityAsync(cityId, finalPointOfInterest); await _cityInfoRepository.SaveChangesAsync(); var createdPointOfInterestToReturn = _mapper.Map(finalPointOfInterest); return CreatedAtRoute("GetPointOfInterest", new { cityId = cityId, pointOfInterestId = createdPointOfInterestToReturn.Id }, createdPointOfInterestToReturn); } [HttpPut("{pointOfInterestId}", Name = "UpdatePointOfInterest")] public async Task UpdatePointOfInterest( int cityId, int pointOfInterestId, PointOfInterestForUpdateDto pointOfInterest) { if (!await _cityInfoRepository.CityExistAsync(cityId)) { return NotFound(); } var pointofInterestEntity = await _cityInfoRepository.GetPointOfInterestForCityAsync(cityId, pointOfInterestId); if (pointofInterestEntity == null) { return NotFound(); } _mapper.Map(pointOfInterest, pointofInterestEntity); await _cityInfoRepository.SaveChangesAsync(); return NoContent(); } [HttpPatch("{pointOfInterestId}", Name = "PartiallyUpdatePointOfInterest")] public async Task PartiallyUpdatePointOfInterest( int cityId, int pointOfInterestId, JsonPatchDocument patchDocument) { if (!await _cityInfoRepository.CityExistAsync(cityId)) { return NotFound(); } var pointofInterestEntity = await _cityInfoRepository.GetPointOfInterestForCityAsync(cityId, pointOfInterestId); if (pointofInterestEntity == null) { return NotFound(); } var pointOfInterestToPatch = _mapper.Map(pointofInterestEntity); patchDocument.ApplyTo(pointOfInterestToPatch, ModelState); if (!ModelState.IsValid) { return BadRequest(ModelState); } if (!TryValidateModel(pointOfInterestToPatch)) { return BadRequest(ModelState); } _mapper.Map(pointOfInterestToPatch, pointofInterestEntity); await _cityInfoRepository.SaveChangesAsync(); return NoContent(); } [HttpDelete("{pointOfInterestId}")] public async Task DeletePointOfInterest( int cityId, int pointOfInterestId) { if (!await _cityInfoRepository.CityExistAsync(cityId)) { return NotFound(); } var pointofInterestEntity = await _cityInfoRepository.GetPointOfInterestForCityAsync(cityId, pointOfInterestId); if (pointofInterestEntity == null) { return NotFound(); } _cityInfoRepository.DeletePointOfInterest(pointofInterestEntity); await _cityInfoRepository.SaveChangesAsync(); _mailService.Send("Point of interest deleted", $"Point of Interest {pointofInterestEntity.Name} with Id {pointofInterestEntity.Id} was deleted."); return NoContent(); } } }