using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RacePlannerApi.Data; using RacePlannerApi.DTOs; using RacePlannerApi.Models; namespace RacePlannerApi.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] public class EventsController : ControllerBase { private readonly RacePlannerDbContext _context; public EventsController(RacePlannerDbContext context) { _context = context; } [HttpPost] [Authorize(Roles = "Organizer")] public async Task> CreateEvent(CreateEventRequest request) { var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(); } var eventEntity = new Event { Name = request.Name, Description = request.Description, EventDate = request.EventDate, Location = request.Location, Category = request.Category, Tags = request.Tags ?? new List(), MaxParticipants = request.MaxParticipants, OrganizerId = userId.Value, Status = EventStatus.Draft }; _context.Events.Add(eventEntity); await _context.SaveChangesAsync(); // Load organizer for response await _context.Entry(eventEntity).Reference(e => e.Organizer).LoadAsync(); return CreatedAtAction( nameof(GetEvent), new { id = eventEntity.Id }, MapToEventDto(eventEntity)); } [HttpGet] [AllowAnonymous] public async Task>> GetEvents( [FromQuery] EventFilterRequest? filter = null) { var query = _context.Events .Include(e => e.Organizer) .Include(e => e.Registrations) .AsQueryable(); // Apply filters if (filter?.Category != null) { query = query.Where(e => e.Category == filter.Category); } if (filter?.Tags != null && filter.Tags.Any()) { query = query.Where(e => e.Tags.Any(t => filter.Tags.Contains(t))); } if (filter?.FromDate != null) { query = query.Where(e => e.EventDate >= filter.FromDate); } if (filter?.ToDate != null) { query = query.Where(e => e.EventDate <= filter.ToDate); } if (filter?.Status != null && Enum.TryParse(filter.Status, out var status)) { query = query.Where(e => e.Status == status); } if (filter?.OrganizerId != null) { query = query.Where(e => e.OrganizerId == filter.OrganizerId); } // Default to showing published events only for anonymous users if (!User.Identity?.IsAuthenticated ?? true) { query = query.Where(e => e.Status == EventStatus.Published); } var events = await query .OrderBy(e => e.EventDate) .ToListAsync(); return Ok(events.Select(MapToEventDto)); } [HttpGet("{id}")] [AllowAnonymous] public async Task> GetEvent(Guid id) { var eventEntity = await _context.Events .Include(e => e.Organizer) .Include(e => e.Registrations) .FirstOrDefaultAsync(e => e.Id == id); if (eventEntity == null) { return NotFound(); } // Draft events only visible to organizers if (eventEntity.Status == EventStatus.Draft) { var userId = GetCurrentUserId(); if (userId == null || eventEntity.OrganizerId != userId) { return NotFound(); } } return Ok(MapToEventDto(eventEntity)); } [HttpPut("{id}")] [Authorize(Roles = "Organizer")] public async Task> UpdateEvent(Guid id, UpdateEventRequest request) { var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(); } var eventEntity = await _context.Events .Include(e => e.Organizer) .FirstOrDefaultAsync(e => e.Id == id); if (eventEntity == null) { return NotFound(); } // Only organizer can update their event if (eventEntity.OrganizerId != userId) { return Forbid(); } // Update fields if (request.Name != null) eventEntity.Name = request.Name; if (request.Description != null) eventEntity.Description = request.Description; if (request.EventDate != null) eventEntity.EventDate = request.EventDate.Value; if (request.Location != null) eventEntity.Location = request.Location; if (request.Status != null) eventEntity.Status = request.Status.Value; if (request.Category != null) eventEntity.Category = request.Category; if (request.Tags != null) eventEntity.Tags = request.Tags; if (request.MaxParticipants != null) eventEntity.MaxParticipants = request.MaxParticipants; eventEntity.UpdatedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); return Ok(MapToEventDto(eventEntity)); } [HttpDelete("{id}")] [Authorize(Roles = "Organizer")] public async Task DeleteEvent(Guid id) { var userId = GetCurrentUserId(); if (userId == null) { return Unauthorized(); } var eventEntity = await _context.Events.FindAsync(id); if (eventEntity == null) { return NotFound(); } if (eventEntity.OrganizerId != userId) { return Forbid(); } _context.Events.Remove(eventEntity); await _context.SaveChangesAsync(); return NoContent(); } private Guid? GetCurrentUserId() { var userIdClaim = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; if (Guid.TryParse(userIdClaim, out var userId)) { return userId; } return null; } private static EventDto MapToEventDto(Event eventEntity) { return new EventDto { Id = eventEntity.Id, Name = eventEntity.Name, Description = eventEntity.Description, EventDate = eventEntity.EventDate, Location = eventEntity.Location, Status = eventEntity.Status.ToString(), Category = eventEntity.Category, Tags = eventEntity.Tags, MaxParticipants = eventEntity.MaxParticipants, CurrentRegistrations = eventEntity.Registrations?.Count ?? 0, CreatedAt = eventEntity.CreatedAt, UpdatedAt = eventEntity.UpdatedAt, Organizer = new UserSummaryDto { Id = eventEntity.Organizer.Id, Name = eventEntity.Organizer.Name, Email = eventEntity.Organizer.Email } }; } }