using Fitness_core_BE.DTOs.Facility; using Fitness_core_BE.Helpers; using Fitness_core_BE.Interfaces.Services; using Fitness_core_BE.Models.IOs; using Microsoft.AspNetCore.Mvc; using static Fitness_core_BE.Helpers.JwtMiddleware; using static Fitness_core_BE.Helpers.ApiResponseHelper; namespace Fitness_core_BE.Controllers { // Staff/owner-facing facility (bookable area + access zone -- merged from the former // Facility/Place split) management. Reads stay on the "bookings" nav permission (the // Bookings page's tabs need the list); mutations (create/edit/status/device-assign) are on // "memberships" since facility setup now lives on the Memberships page. [ApiController] [Route("api/client/facilities")] public class FacilityController(IFacilityService facilityService) : ControllerBase { private readonly IFacilityService _facilityService = facilityService; [CustomMiddleware] [TenantResolution] [RequiresPermission("bookings")] [HttpGet("")] public async Task>> GetAllFacilities([FromQuery] bool includeInactive = false) => Response(await _facilityService.GetAllFacilities(new { includeInactive }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("memberships")] [HttpPost("")] public async Task>> CreateFacility([FromBody] CreateFacilityRequest request) => Response(await _facilityService.CreateFacility(new { name = request.Name, bookingMode = request.BookingMode, description = request.Description, defaultCapacity = request.DefaultCapacity, numberOfUnits = request.NumberOfUnits, pricePerHour = request.PricePerHour }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("memberships")] [HttpPut("{id:guid}")] public async Task>> UpdateFacility(Guid id, [FromBody] UpdateFacilityRequest request) { var payload = new Dictionary { ["facilityId"] = id }; if (request.Name != null) payload["name"] = request.Name; if (request.BookingMode != null) payload["bookingMode"] = request.BookingMode; if (request.Description != null) payload["description"] = request.Description; if (request.DefaultCapacity.HasValue) payload["defaultCapacity"] = request.DefaultCapacity.Value; if (request.NumberOfUnits.HasValue) payload["numberOfUnits"] = request.NumberOfUnits.Value; if (request.PricePerHour.HasValue) payload["pricePerHour"] = request.PricePerHour.Value; if (request.IsActive.HasValue) payload["isActive"] = request.IsActive.Value; return Response(await _facilityService.UpdateFacility(payload, HttpContext)); } [CustomMiddleware] [TenantResolution] [RequiresPermission("memberships")] [HttpPatch("{id:guid}/status")] public async Task>> SetFacilityStatus(Guid id, [FromBody] SetFacilityStatusRequest request) => Response(await _facilityService.SetFacilityStatus(new { facilityId = id, isActive = request.IsActive }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("memberships")] [HttpPut("{id:guid}/device")] public async Task>> AssignDevice(Guid id, [FromBody] AssignFacilityDeviceRequest request) => Response(await _facilityService.AssignDevice(new { facilityId = id, deviceId = request.DeviceId }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("bookings")] [HttpPost("sessions")] public async Task>> CreateFacilitySession([FromBody] CreateFacilitySessionRequest request) => Response(await _facilityService.CreateFacilitySession(new { facilityId = request.FacilityId, startTime = request.StartTime.ToString("o"), endTime = request.EndTime.ToString("o"), capacity = request.Capacity }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("bookings")] [HttpGet("sessions")] public async Task>> GetSessions( [FromQuery] Guid? facilityId, [FromQuery] DateTime? fromDate, [FromQuery] DateTime? toDate) => Response(await _facilityService.GetSessions(new { facilityId, fromDate = fromDate?.ToString("o"), toDate = toDate?.ToString("o") }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("bookings")] [HttpDelete("sessions/{id:guid}")] public async Task>> CancelFacilitySession(Guid id) => Response(await _facilityService.CancelFacilitySession(new { facilitySessionId = id }, HttpContext)); [CustomMiddleware] [TenantResolution] [RequiresPermission("bookings")] [HttpGet("availability")] public async Task>> GetAvailability( [FromQuery] Guid? facilityId, [FromQuery] DateTime startTime, [FromQuery] int durationMinutes) => Response(await _facilityService.GetAvailability(new { facilityId, startTime = startTime.ToString("o"), durationMinutes }, HttpContext)); } }