using Nexus.Api.Data;
using Nexus.Api.Integrations;
using Nexus.Api.Repositories;

namespace Nexus.Api.Services;

public sealed class OperationsService(
    IAgentRuntime runtime,
    IAgentService agentService,
    IProjectRepository projectRepo,
    ITaskRepository taskRepo,
    IActivityRepository activityRepo) : IOperationsService
{
    public async Task<object> GetSnapshotAsync(CancellationToken ct = default)
    {
        var runtimeTask = runtime.GetStatusAsync(ct);
        var agentsTask = agentService.GetAgentsAsync(ct);
        // Repository calls share the scoped EF Core DbContext and must stay serialized.
        var projects = await projectRepo.GetAllAsync(ct);
        var tasks = await taskRepo.GetAllAsync(ct);
        var activity = await activityRepo.GetRecentAsync(20, ct);
        var agents = await agentsTask;
        var completedTasks = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Done));
        var runtimeStatus = await runtimeTask;

        var lastIncident = tasks
            .Where(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked))
            .OrderByDescending(x => x.UpdatedAt)
            .Select(x => new { TaskId = (Guid?)x.Id, Title = (string?)x.Title, Since = (DateTimeOffset?)x.UpdatedAt })
            .FirstOrDefault();

        return new
        {
            generatedAt = DateTimeOffset.UtcNow,
            runtime = runtimeStatus,
            models = Array.Empty<object>(),
            runtimeHealthy = runtimeStatus.Status == OperationalStatus.Online,
            metrics = new
            {
                activeAgents = agents.Count,
                queuedTasks = tasks.Count - completedTasks,
                successRate = tasks.Count == 0 ? 100 : Math.Round(completedTasks * 100d / tasks.Count, 1),
                incidents = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked))
            },
            lastIncident,
            projectHealth = new
            {
                Online = projects.Count(x => x.Status == OperationalStatus.Online),
                Offline = projects.Count(x => x.Status == OperationalStatus.Offline),
                Degraded = projects.Count(x => x.Status == OperationalStatus.Degraded),
                Unknown = projects.Count(x => x.Status == OperationalStatus.Unknown)
            },
            agents = agents.Select(x => new { x.Id, x.Name, x.Role, x.Status, x.Model }),
            projects = projects.Select(x => new { x.Id, x.Name, x.Status, x.Progress, x.UpdatedAt }),
            tasks = tasks.Select(x => new { x.Id, x.Title, x.State, x.Priority, x.ProjectId, x.UpdatedAt }),
            activity = activity.Select(x => new { x.Id, x.Type, x.Message, at = x.CreatedAt })
        };
    }
}
