using System.Net.Http.Headers;
using System.Net.Http.Json;
using Nexus.Api.DTOs;

namespace Nexus.Api.Services;

public sealed class CalendarService(
    IHttpClientFactory httpClientFactory,
    IConfiguration configuration,
    ILogger<CalendarService> logger) : ICalendarService
{
    public async Task<IReadOnlyList<CronJobEntry>> GetCronJobsAsync(CancellationToken ct = default)
    {
        try
        {
            var client = CreateGatewayClient();
            var response = await client.GetAsync("/api/cron", ct);
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadFromJsonAsync<List<CronJobEntry>>(ct);
                return data ?? new List<CronJobEntry>();
            }
        }
        catch (Exception ex)
        {
            logger.LogDebug(ex, "Gateway cron endpoint not reachable, using fallback data");
        }

        return BuildFallbackCronJobs();
    }

    public async Task<IReadOnlyList<UpcomingCronEntry>> GetUpcomingCronJobsAsync(CancellationToken ct = default)
    {
        try
        {
            var client = CreateGatewayClient();
            var response = await client.GetAsync("/api/cron/upcoming", ct);
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadFromJsonAsync<List<UpcomingCronEntry>>(ct);
                return data ?? new List<UpcomingCronEntry>();
            }
        }
        catch (Exception ex)
        {
            logger.LogDebug(ex, "Gateway upcoming cron endpoint not reachable, using fallback data");
        }

        return BuildFallbackUpcomingJobs();
    }

    private HttpClient CreateGatewayClient()
    {
        var client = httpClientFactory.CreateClient("gateway");
        var token = configuration["Integrations:OpenClaw:Token"];
        if (!string.IsNullOrWhiteSpace(token))
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        return client;
    }

    private static IReadOnlyList<CronJobEntry> BuildFallbackCronJobs()
    {
        var now = DateTimeOffset.UtcNow;
        return
        [
            new("health-check", "Health Check", "*/5 * * * *", now.AddMinutes(-3).ToString("O"), now.AddMinutes(2).ToString("O"), "completed"),
            new("memory-sync", "Memory Sync", "0 */6 * * *", now.AddHours(-2).ToString("O"), now.AddHours(4).ToString("O"), "completed"),
            new("task-cleanup", "Task Cleanup", "0 3 * * *", now.AddDays(-1).ToString("O"), now.AddDays(1).AddHours(3).ToString("O"), "completed"),
            new("backup", "Database Backup", "0 4 * * *", now.AddDays(-1).AddHours(-1).ToString("O"), now.AddDays(1).AddHours(4).ToString("O"), "completed"),
            new("model-routing-refresh", "Model Routing Refresh", "*/30 * * * *", now.AddMinutes(-12).ToString("O"), now.AddMinutes(18).ToString("O"), "running")
        ];
    }

    private static IReadOnlyList<UpcomingCronEntry> BuildFallbackUpcomingJobs()
    {
        var now = DateTimeOffset.UtcNow;
        return
        [
            new("health-check", "Health Check", now.AddMinutes(2).ToString("O"), "*/5 * * * *"),
            new("model-routing-refresh", "Model Routing Refresh", now.AddMinutes(18).ToString("O"), "*/30 * * * *"),
            new("memory-sync", "Memory Sync", now.AddHours(4).ToString("O"), "0 */6 * * *"),
            new("task-cleanup", "Task Cleanup", now.AddDays(1).AddHours(3).ToString("O"), "0 3 * * *"),
            new("backup", "Database Backup", now.AddDays(1).AddHours(4).ToString("O"), "0 4 * * *")
        ];
    }
}
