using Microsoft.AspNetCore.Mvc; using Nexus.Api.DTOs; namespace Nexus.Api.Controllers; [ApiController] [Route("api/v1/calendar")] public class CalendarController(IConfiguration config, IHttpClientFactory httpClientFactory, ILogger logger) : ControllerBase { [HttpGet] public async Task GetAll(CancellationToken ct) { var gatewayToken = config["Integrations:OpenClaw:Token"] ?? ""; try { var httpClient = httpClientFactory.CreateClient("gateway"); if (!string.IsNullOrWhiteSpace(gatewayToken)) httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", gatewayToken); var response = await httpClient.GetAsync("/api/cron", ct); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadFromJsonAsync>(ct); return Results.Ok(data ?? new List()); } } catch (Exception ex) { logger.LogDebug(ex, "Gateway cron endpoint not reachable, using fallback data."); } var fallbackJobs = new List { new { id = "health-check", name = "Health Check", schedule = "*/5 * * * *", lastRun = DateTimeOffset.UtcNow.AddMinutes(-3).ToString("O"), nextRun = DateTimeOffset.UtcNow.AddMinutes(2).ToString("O"), status = "completed" }, new { id = "memory-sync", name = "Memory Sync", schedule = "0 */6 * * *", lastRun = DateTimeOffset.UtcNow.AddHours(-2).ToString("O"), nextRun = DateTimeOffset.UtcNow.AddHours(4).ToString("O"), status = "completed" }, new { id = "task-cleanup", name = "Task Cleanup", schedule = "0 3 * * *", lastRun = DateTimeOffset.UtcNow.AddDays(-1).ToString("O"), nextRun = DateTimeOffset.UtcNow.AddDays(1).AddHours(3).ToString("O"), status = "completed" }, new { id = "backup", name = "Database Backup", schedule = "0 4 * * *", lastRun = DateTimeOffset.UtcNow.AddDays(-1).AddHours(-1).ToString("O"), nextRun = DateTimeOffset.UtcNow.AddDays(1).AddHours(4).ToString("O"), status = "completed" }, new { id = "model-routing-refresh", name = "Model Routing Refresh", schedule = "*/30 * * * *", lastRun = DateTimeOffset.UtcNow.AddMinutes(-12).ToString("O"), nextRun = DateTimeOffset.UtcNow.AddMinutes(18).ToString("O"), status = "running" }, }; return Results.Ok(fallbackJobs); } [HttpGet("upcoming")] public async Task GetUpcoming(CancellationToken ct) { var gatewayToken = config["Integrations:OpenClaw:Token"] ?? ""; try { var httpClient = httpClientFactory.CreateClient("gateway"); if (!string.IsNullOrWhiteSpace(gatewayToken)) httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", gatewayToken); var response = await httpClient.GetAsync("/api/cron/upcoming", ct); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadFromJsonAsync>(ct); return Results.Ok(data ?? new List()); } } catch (Exception ex) { logger.LogDebug(ex, "Gateway upcoming cron endpoint not reachable, using fallback data."); } var now = DateTimeOffset.UtcNow; var fallback = new List { new { id = "health-check", name = "Health Check", nextRun = now.AddMinutes(2).ToString("O"), schedule = "*/5 * * * *" }, new { id = "model-routing-refresh", name = "Model Routing Refresh", nextRun = now.AddMinutes(18).ToString("O"), schedule = "*/30 * * * *" }, new { id = "memory-sync", name = "Memory Sync", nextRun = now.AddHours(4).ToString("O"), schedule = "0 */6 * * *" }, new { id = "task-cleanup", name = "Task Cleanup", nextRun = now.AddDays(1).AddHours(3).ToString("O"), schedule = "0 3 * * *" }, new { id = "backup", name = "Database Backup", nextRun = now.AddDays(1).AddHours(4).ToString("O"), schedule = "0 4 * * *" }, }; return Results.Ok(fallback); } }