using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using QuestionsApi.Models; using QuestionsApi.Services; using System.Security.Claims; namespace QuestionsApi.Controllers; [ApiController] [Route("api/ccs")] [Authorize(Roles = "USER,SUPER")] public sealed class CcsController(CcsStore store, CcsRatingStore ratings) : ControllerBase { [HttpGet("cases")] public async Task Cases() => Ok(await store.ListCasesAsync()); [HttpGet("orders/search")] public async Task SearchOrders([FromQuery] string q, [FromQuery] int limit = 20) => Ok(await store.SearchOrdersAsync(q ?? "", limit)); [HttpPost("attempts")] public async Task CreateAttempt(CreateCcsAttemptRequest request) { try { return Ok(await store.ToResponseAsync(await store.CreateAttemptAsync(UserId(), request))); } catch (ArgumentException exception) { return BadRequest(exception.Message); } catch (KeyNotFoundException) { return NotFound(); } catch (InvalidOperationException exception) { return Conflict(exception.Message); } } [HttpGet("attempts/{id}")] public async Task Attempt(string id) { var attempt = await store.GetOwnedAsync(id, UserId()); return attempt is null ? NotFound() : Ok(await store.ToResponseAsync(attempt)); } [HttpPost("attempts/{id}/commands")] public async Task Command(string id, CcsCommandRequest request) { var attempt = await store.GetOwnedAsync(id, UserId()); if (attempt is null) return NotFound(); try { return Ok(await store.ToResponseAsync(await store.ApplyCommandAsync(attempt, request))); } catch (ArgumentException exception) { return BadRequest(exception.Message); } catch (InvalidOperationException exception) { return Conflict(exception.Message); } } [HttpPost("attempts/{id}/abandon")] public async Task Abandon(string id) { var attempt = await store.GetOwnedAsync(id, UserId()); if (attempt is null) return NotFound(); await store.AbandonAsync(attempt); return NoContent(); } [HttpGet("history")] public async Task History([FromQuery] int limit = 50) => Ok(await store.HistoryAsync(UserId(), limit)); [HttpGet("prediction")] public async Task Prediction() => Ok(await store.PredictionAsync(UserId())); [HttpGet("ratings/me")] public async Task Rating() => Ok(await ratings.GetProfileAsync(UserId())); [HttpPost("admin/import")] [Authorize(Roles = "SUPER")] public async Task Import(CcsImportRequest request) { var response = await store.ImportAsync(request); return response.Errors.Count > 0 ? BadRequest(response) : Ok(response); } private string UserId() => User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue(ClaimTypes.Name) ?? User.Identity?.Name ?? throw new UnauthorizedAccessException(); }