using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using WondersAPI.Data; using WondersAPI.Models; namespace Ghaymah.WondersAPI.Controllers { /// /// API controller to manage Wonders (CRUD + Random). /// [ApiController] [Route("api/[controller]")] public class WondersController : ControllerBase { private readonly AppDbContext _context; private readonly ILogger _logger; public WondersController(AppDbContext context, ILogger logger) { _context = context; _logger = logger; } // -------------------- GET ALL -------------------- /// /// Get all wonders. /// /// List of all wonders. [HttpGet] [ProducesResponseType(typeof(IEnumerable), 200)] public async Task GetAllWonders() { var wonders = await FetchAllWonders(); LogFetchedWonders(wonders.Count); return Ok(wonders); } private async Task> FetchAllWonders() => await _context.Wonders.ToListAsync(); private void LogFetchedWonders(int count) => _logger.LogInformation("Fetched {Count} wonders from database", count); // -------------------- GET BY ID -------------------- /// /// Get a specific wonder by its ID. /// /// The ID of the wonder. /// The wonder with the specified ID. [HttpGet("{id}")] [ProducesResponseType(typeof(Wonder), 200)] [ProducesResponseType(404)] public async Task GetWonderById(int wonderId) { var wonder = await FindWonderOrNotFound(wonderId); if (wonder is null) return NotFound(new { message = $"Wonder with ID {wonderId} not found" }); return Ok(wonder); } private async Task FindWonderOrNotFound(int wonderId) => await _context.Wonders.FindAsync(wonderId); // -------------------- CREATE -------------------- /// /// Create a new wonder. /// /// The wonder to create. /// The created wonder. [HttpPost] [ProducesResponseType(typeof(Wonder), 201)] public async Task CreateWonder([FromBody] Wonder newWonder) => await SaveNewWonder(newWonder); private async Task SaveNewWonder(Wonder wonder) { _context.Wonders.Add(wonder); await _context.SaveChangesAsync(); LogCreatedWonder(wonder.Name); return CreatedAtAction(nameof(GetWonderById), new { wonderId = wonder.Id }, wonder); } private void LogCreatedWonder(string name) => _logger.LogInformation("Created new wonder: {Name}", name); // -------------------- UPDATE -------------------- /// /// Update an existing wonder. /// /// The ID of the wonder to update. /// The updated wonder data. [HttpPut("{id}")] [ProducesResponseType(204)] [ProducesResponseType(404)] public async Task UpdateWonder(int wonderId, [FromBody] Wonder updatedWonder) { var existingWonder = await FindWonderOrNotFound(wonderId); if (existingWonder is null) return NotFound(); return await SaveUpdatedWonder(existingWonder, updatedWonder); } private async Task SaveUpdatedWonder(Wonder target, Wonder source) { CopyWonderValues(target, source); await _context.SaveChangesAsync(); LogUpdatedWonder(target.Id); return NoContent(); } private void CopyWonderValues(Wonder target, Wonder source) { target.Name = source.Name; target.Country = source.Country; target.Era = source.Era; target.Type = source.Type; target.Description = source.Description; target.DiscoveryYear = source.DiscoveryYear; } private void LogUpdatedWonder(int wonderId) => _logger.LogInformation("Updated wonder with ID {Id}", wonderId); // -------------------- DELETE -------------------- /// /// Delete a wonder by ID. /// /// The ID of the wonder to delete. [HttpDelete("{id}")] [ProducesResponseType(204)] [ProducesResponseType(404)] public async Task DeleteWonder(int wonderId) { var wonder = await FindWonderOrNotFound(wonderId); if (wonder is null) return NotFound(); await RemoveWonder(wonder); return NoContent(); } private async Task RemoveWonder(Wonder wonder) { _context.Wonders.Remove(wonder); await _context.SaveChangesAsync(); LogDeletedWonder(wonder.Id); } private void LogDeletedWonder(int wonderId) => _logger.LogInformation("Deleted wonder with ID {Id}", wonderId); // -------------------- GET RANDOM -------------------- /// /// Get a random wonder. /// /// A randomly selected wonder. [HttpGet("random")] [ProducesResponseType(typeof(Wonder), 200)] [ProducesResponseType(404)] public async Task GetRandomWonder() { var allWonders = await FetchAllWonders(); if (!allWonders.Any()) return NotFound(); var randomWonder = SelectRandomWonder(allWonders); LogRandomWonder(randomWonder.Name); return Ok(randomWonder); } private Wonder SelectRandomWonder(List wonders) => wonders[new Random().Next(wonders.Count)]; private void LogRandomWonder(string name) => _logger.LogInformation("Returned random wonder: {Name}", name); } }