using System.ComponentModel.DataAnnotations; using System.Text.Json; using API.DTO; using API.Validation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Model; using Services; namespace API.Controllers; [ApiController] public class TacticController(ITacticService service) : ControllerBase { public record UpdateNameRequest( [StringLength(50, MinimumLength = 1)] [Name] string Name); [HttpPut("/tactics/{tacticId:int}/name")] [Authorize] public async Task UpdateName( int tacticId, [FromBody] UpdateNameRequest req) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } var result = await service.UpdateName(tacticId, req.Name); return result ? Ok() : NotFound(); } [HttpGet("/tactics/{tacticId:int}")] [Authorize] public async Task GetTacticInfo(int tacticId) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } var result = await service.GetTactic(tacticId); return result != null ? Ok(result.ToDto()) : NotFound(); } public record GetTacticStepsTreeResponse(TacticStepDto Root); [HttpGet("/tactics/{tacticId:int}/tree")] [Authorize] public async Task GetTacticStepsRoot(int tacticId) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } var root = (await service.GetRootStep(tacticId)).ToDto(); return Ok(new GetTacticStepsTreeResponse(root)); } public record CreateNewRequest( [StringLength(50, MinimumLength = 1)] [Name] string Name, [AllowedValues("PLAIN", "HALF")] string CourtType ); public record CreateNewResponse(int Id); [HttpPost("/tactics")] [Authorize] public async Task CreateNew([FromBody] CreateNewRequest req) { var userId = this.CurrentUserId(); var courtType = req.CourtType switch { "PLAIN" => CourtType.Plain, "HALF" => CourtType.Half, _ => throw new ArgumentOutOfRangeException() //unreachable }; var id = await service.AddTactic(userId, req.Name, courtType); return new CreateNewResponse(id); } public record AddStepRequest(int ParentId, object Content); public record AddStepResponse(int StepId); [HttpPost("/tactics/{tacticId:int}/steps")] public async Task AddStep(int tacticId, [FromBody] AddStepRequest req) { var stepId = await service.AddTacticStep(tacticId, req.ParentId, JsonSerializer.Serialize(req.Content)); return stepId != null ? Ok(new AddStepResponse(stepId ?? 0)) : NotFound(); } [HttpGet("/tactics/{tacticId:int}/steps/{stepId:int}")] [Authorize] public async Task GetStepContent(int tacticId, int stepId) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } var json = await service.GetTacticStepContent(tacticId, stepId); return json != null ? Ok(JsonSerializer.Deserialize(json)) : NotFound(); } [HttpDelete("/tactics/{tacticId:int}/steps/{stepId:int}")] [Authorize] public async Task RemoveStepContent(int tacticId, int stepId) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } var found = await service.RemoveTacticStep(tacticId, stepId); return found ? Ok() : NotFound(); } public record SaveStepContentRequest(object Content); [HttpPut("/tactics/{tacticId:int}/steps/{stepId:int}")] [Authorize] public async Task SaveStepContent(int tacticId, int stepId, [FromBody] SaveStepContentRequest req) { var userId = this.CurrentUserId(); if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } await service.SetTacticStepContent(tacticId, stepId, JsonSerializer.Serialize(req.Content)); return Ok(); } }