using Asp.Versioning; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TarninaHub.Application.Abstractions; using TarninaHub.Application.Dtos; using TarninaHub.Application.Mappings; using TarninaHub.Application.Security; namespace TarninaHub.Controllers; [ApiController] [ApiVersion("1.0")] [Route("api/innovations")] [Authorize] public class InnovationsController : ControllerBase { private readonly IInnovationService _innovations; private readonly IMatchmakingService _matchmakingService; public InnovationsController(IInnovationService innovations, IMatchmakingService matchmakingService) { _innovations = innovations; _matchmakingService = matchmakingService; } [HttpGet] public async Task>> List( [FromQuery] string? challengeId, [FromQuery] string? stage, [FromQuery] string? q, CancellationToken cancellationToken) { var innovations = await _innovations.ListAsync(challengeId, stage, q, !IsStaff(), cancellationToken); return Ok(innovations); } [HttpGet("{innovationId}")] public async Task> GetById( string innovationId, CancellationToken cancellationToken) { var innovation = await _innovations.GetAsync(innovationId, cancellationToken); return innovation is null ? NotFound() : Ok(innovation); } [HttpPost] [Authorize(Policy = Policies.OperatorOrAdmin)] public async Task> Create( InnovationRequest request, CancellationToken cancellationToken) { if (!ValidateStage(request.Stage)) { return InvalidStage(); } var created = await _innovations.CreateAsync(request, cancellationToken); await _matchmakingService.IndexInnovationAsync(created.Id, cancellationToken); return CreatedAtAction(nameof(GetById), new { innovationId = created.Id }, created); } [HttpPut("{innovationId}")] [Authorize(Policy = Policies.OperatorOrAdmin)] public async Task> Update( string innovationId, InnovationRequest request, CancellationToken cancellationToken) { if (!ValidateStage(request.Stage)) { return InvalidStage(); } var updated = await _innovations.UpdateAsync(innovationId, request, cancellationToken); if (updated is not null) { await _matchmakingService.IndexInnovationAsync(updated.Id, cancellationToken); } return updated is null ? NotFound() : Ok(updated); } private bool ValidateStage(string? stage) => InnovationStageWire.IsValid(stage); private ActionResult InvalidStage() { ModelState.AddModelError(nameof(InnovationRequest.Stage), "Stage must be one of: idea, pilot, scaling, service."); return ValidationProblem(ModelState); } private bool IsStaff() => User.IsInRole(RoleNames.Operator) || User.IsInRole(RoleNames.Manager) || User.IsInRole(RoleNames.Admin); }