using Management.Data; using Management.Security; using Microsoft.AspNetCore.Mvc; using System.Text.Json; namespace Management.Controllers; /// /// Monitoring endpoints for system health and stats. /// Requires Admin session. /// /// ENDPOINTS: /// GET /api/monitoring/health - System health overview /// GET /api/monitoring/stats - Detailed statistics /// [ApiController] [Route("api/monitoring")] public sealed class MonitoringController : ControllerBase { private readonly SqlService _sql; private readonly ClientContext _client; private readonly ILogger _log; private readonly Management.Services.GraphService _graph; public MonitoringController(SqlService sql, ClientContext client, Management.Services.GraphService graph, ILogger log) { _sql = sql; _client = client; _graph = graph; _log = log; } /// /// System health overview. /// [HttpGet("health")] public async Task Health(CancellationToken ct) { try { var resp = await _sql.ExecProcAsync("dbo.spMonitoring", "health", "{}", ct: ct); if (string.IsNullOrWhiteSpace(resp)) return StatusCode(500, new { ok = false, error = "Service unavailable" }); return Content(resp, "application/json"); } catch (Exception ex) { _log.LogError(ex, "[Monitoring] Health error"); return StatusCode(500, new { ok = false, error = "Health check failed", detail = ex.Message }); } } /// /// Detailed system statistics. /// [HttpPost("stats")] public async Task Stats([FromBody] JsonElement body, CancellationToken ct) { var rqst = body.ToString(); try { var resp = await _sql.ExecProcAsync("dbo.spMonitoring", "stats", rqst, ct: ct); if (string.IsNullOrWhiteSpace(resp)) return StatusCode(500, new { ok = false, error = "Service unavailable" }); return Content(resp, "application/json"); } catch (Exception ex) { _log.LogError(ex, "[Monitoring] Stats error"); return StatusCode(500, new { ok = false, error = "Stats failed", detail = ex.Message }); } } /// /// Staff user list — distinct staff who have ever performed an action, /// derived directly from tbAdminActivity. /// [HttpGet("staff")] public async Task Staff(CancellationToken ct) { try { var json = await _sql.ExecProcAsync("dbo.spAdminActivity", "distinct-staff", "{}", ct: ct); return Content(json, "application/json"); } catch (Exception ex) { _log.LogError(ex, "[Monitoring] Staff list error"); return StatusCode(500, new { ok = false, error = "Staff list failed", detail = ex.Message }); } } /// /// Admin activity log — all mutating requests by staff members. /// Accessible to Staff.Admin and Staff.Tech. /// Body: { oid?, dateFrom?, dateTo?, page?, pageSize? } /// [HttpPost("activity")] public async Task Activity([FromBody] JsonElement body, CancellationToken ct) { try { var resp = await _sql.ExecProcAsync("dbo.spAdminActivity", "list", body.ToString(), ct: ct); if (string.IsNullOrWhiteSpace(resp)) return StatusCode(500, new { ok = false, error = "Service unavailable" }); return Content(resp, "application/json"); } catch (Exception ex) { _log.LogError(ex, "[Monitoring] Activity log error"); return StatusCode(500, new { ok = false, error = "Activity log failed", detail = ex.Message }); } } }