using Asp.Versioning; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TarninaHub.Application.Abstractions; using TarninaHub.Application.Dtos; using TarninaHub.Application.Security; namespace TarninaHub.Controllers; [ApiController] [ApiVersion("1.0")] [Route("api/admin")] [Authorize(Policy = Policies.OperatorOrAdmin)] public class AdminController : ControllerBase { private readonly IAdminService _admin; private readonly IGrantCallService _grantCalls; private readonly IIdeaService _ideas; private readonly INotificationService _notifications; public AdminController( IAdminService admin, IGrantCallService grantCalls, IIdeaService ideas, INotificationService notifications) { _admin = admin; _grantCalls = grantCalls; _ideas = ideas; _notifications = notifications; } [HttpGet("submissions")] public async Task>> ListSubmissions( [FromQuery] string? status, [FromQuery] string? challengeId, CancellationToken cancellationToken) { var submissions = await _admin.ListSubmissionsAsync(status, challengeId, cancellationToken); return Ok(submissions); } [HttpPut("knowledge-items/{knowledgeItemId}/verify")] public async Task> VerifyKnowledgeItem( string knowledgeItemId, VerifyKnowledgeItemRequest request, CancellationToken cancellationToken) { var item = await _admin.VerifyKnowledgeItemAsync(knowledgeItemId, request, cancellationToken); return item is null ? NotFound() : Ok(item); } [HttpGet("metrics")] public async Task> Metrics(CancellationToken cancellationToken) { var metrics = await _admin.GetMetricsAsync(cancellationToken); return Ok(metrics); } [HttpPut("grant-calls/{grantCallId}/status")] public async Task> UpdateGrantCallStatus( string grantCallId, UpdateGrantCallStatusRequest request, CancellationToken cancellationToken) { var updated = await _grantCalls.UpdateStatusAsync(grantCallId, request.Status, cancellationToken); if (updated is null) { return NotFound(); } if (string.Equals(request.Status, "open", StringComparison.Ordinal)) { await NotifyIdeaAuthorsAsync(updated, cancellationToken); } return Ok(updated); } private async Task NotifyIdeaAuthorsAsync(GrantCallResponse call, CancellationToken cancellationToken) { var authorIds = await _ideas.ListDistinctAuthorIdsAsync(cancellationToken); var payload = new Dictionary { ["grantCallId"] = call.Id, ["name"] = call.Name, }; foreach (var authorId in authorIds) { await _notifications.NotifyUserAsync(authorId, "grant_call.opened", payload, cancellationToken); } } }