using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using RobotNet10.NavigationTune.Shared.Interfaces; using RobotNet10.NavigationTune.Shared.Models; namespace RobotNet10.NavigationTune.Controllers; /// /// REST API controller for test runs (test history) /// [ApiController] [Route("api/[controller]")] public class TestRunsController : ControllerBase { private readonly ITestRepository _testRepository; private readonly ILogger _logger; public TestRunsController( ITestRepository testRepository, ILogger logger) { _testRepository = testRepository; _logger = logger; } /// /// Get test runs with optional pagination (returns DTO to avoid abstract TestScenario deserialization on client). /// Use skip/take for paging; totalCount is returned for paginator. /// [HttpGet] public async Task>> GetAll( [FromQuery] int? skip = null, [FromQuery] int? take = null, [FromQuery] int? limit = null) { try { int skipVal = skip ?? 0; int takeVal; if (limit.HasValue && limit.Value > 0 && !take.HasValue) takeVal = limit.Value; else takeVal = Math.Min(take ?? 50, 500); var totalCount = await _testRepository.GetCountAsync(); var testRuns = await _testRepository.GetPagedAsync(skipVal, takeVal); var items = testRuns.Select(ToDto).ToList(); return Ok(new PagedResult { TotalCount = totalCount, Items = items }); } catch (Exception ex) { _logger.LogError(ex, "Error getting all test runs"); return StatusCode(500, new { error = "Failed to retrieve test runs" }); } } /// /// Get test run by ID /// [HttpGet("{id:guid}")] public async Task> GetById(Guid id) { try { var testRun = await _testRepository.GetByIdAsync(id); if (testRun == null) return NotFound(new { error = $"Test run with ID {id} not found" }); return Ok(ToDto(testRun)); } catch (Exception ex) { _logger.LogError(ex, "Error getting test run {Id}", id); return StatusCode(500, new { error = "Failed to retrieve test run" }); } } /// /// Get test runs by scenario ID /// [HttpGet("scenario/{scenarioId}")] public async Task>> GetByScenario(Guid scenarioId) { try { var testRuns = await _testRepository.GetByScenarioAsync(scenarioId); return Ok(testRuns.Select(ToDto).ToList()); } catch (Exception ex) { _logger.LogError(ex, "Error getting test runs for scenario {ScenarioId}", scenarioId); return StatusCode(500, new { error = "Failed to retrieve test runs" }); } } /// /// Get test runs by parameter set ID /// [HttpGet("parameterset/{parameterSetId}")] public async Task>> GetByParameterSet(Guid parameterSetId) { try { var testRuns = await _testRepository.GetByParameterSetAsync(parameterSetId); return Ok(testRuns.Select(ToDto).ToList()); } catch (Exception ex) { _logger.LogError(ex, "Error getting test runs for parameter set {ParameterSetId}", parameterSetId); return StatusCode(500, new { error = "Failed to retrieve test runs" }); } } /// /// Get test runs by date range /// [HttpGet("daterange")] public async Task>> GetByDateRange( [FromQuery] DateTime from, [FromQuery] DateTime to) { try { var testRuns = await _testRepository.GetByDateRangeAsync(from, to); return Ok(testRuns.Select(ToDto).ToList()); } catch (Exception ex) { _logger.LogError(ex, "Error getting test runs for date range {From} to {To}", from, to); return StatusCode(500, new { error = "Failed to retrieve test runs" }); } } /// /// Delete test run /// [HttpDelete("{id}")] public async Task Delete(Guid id) { try { var existing = await _testRepository.GetByIdAsync(id); if (existing == null) return NotFound(new { error = $"Test run with ID {id} not found" }); await _testRepository.DeleteAsync(id); return NoContent(); } catch (Exception ex) { _logger.LogError(ex, "Error deleting test run {Id}", id); return StatusCode(500, new { error = "Failed to delete test run" }); } } /// /// Delete multiple test runs by IDs /// [HttpPost("delete-batch")] public async Task DeleteBatch([FromBody] DeleteBatchRequest request) { if (request?.Ids == null || request.Ids.Count == 0) return BadRequest(new { error = "Ids is required and must not be empty" }); try { await _testRepository.DeleteManyAsync(request.Ids); return NoContent(); } catch (Exception ex) { _logger.LogError(ex, "Error deleting test runs batch"); return StatusCode(500, new { error = "Failed to delete test runs" }); } } private static TestRunDto ToDto(TestRun r) { return new TestRunDto { Id = r.Id, ScenarioId = r.ScenarioId, ScenarioName = r.Scenario?.Name ?? string.Empty, ParameterSetId = r.ParameterSetId, ParameterSetName = r.ParameterSet?.Name ?? string.Empty, StartTime = r.StartTime, EndTime = r.EndTime, Status = r.Status, Duration = r.Duration, Notes = r.Notes, ErrorMessage = r.ErrorMessage, Metrics = r.Metrics, SafetyViolations = r.SafetyViolations ?? new List() }; } }