using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Nexus.Api.Integrations;

namespace Nexus.Api.Controllers;

[ApiController]
public class HealthController(IAgentRuntime runtime, HealthCheckService healthChecks) : ControllerBase
{
    [AllowAnonymous]
    [HttpGet("/health/live")]
    public IResult Live()
        => Results.Ok(new
        {
            status = "Healthy",
            timestamp = DateTimeOffset.UtcNow,
            agentSource = "openclaw-rpc"
        });

    [AllowAnonymous]
    [HttpGet("/health/ready")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
    public async Task<IResult> Ready(CancellationToken ct)
    {
        var report = await healthChecks.CheckHealthAsync(
            registration => registration.Tags.Contains("ready"),
            ct);
        var payload = new
        {
            status = report.Status == HealthStatus.Healthy ? "Healthy" : "Unhealthy",
            timestamp = DateTimeOffset.UtcNow
        };

        return report.Status == HealthStatus.Healthy
            ? Results.Ok(payload)
            : Results.Json(payload, statusCode: StatusCodes.Status503ServiceUnavailable);
    }

    [AllowAnonymous]
    [HttpGet("/health")]
    public async Task<IResult> Get(CancellationToken ct)
    {
        var report = await healthChecks.CheckHealthAsync(ct);

        string runtimeStatus;
        string? runtimeDetail;
        try
        {
            var status = await runtime.GetStatusAsync(ct);
            runtimeStatus = status.Status.ToString();
            runtimeDetail = status.Detail;
        }
        catch (Exception ex)
        {
            runtimeStatus = "Offline";
            runtimeDetail = ex.Message;
        }

        static IReadOnlyDictionary<string, object?> NormalizeData(IReadOnlyDictionary<string, object> source)
        {
            return source.ToDictionary(kvp => kvp.Key, kvp => (object?)kvp.Value);
        }

        var entries = report.Entries.ToDictionary(
            e => e.Key,
            e => new
            {
                status = e.Value.Status.ToString(),
                description = e.Value.Description,
                data = NormalizeData(e.Value.Data)
            });

        entries["runtime"] = new
        {
            status = runtimeStatus,
            description = runtimeDetail,
            data = new Dictionary<string, object?>() as IReadOnlyDictionary<string, object?>
        };

        var isHealthy = report.Status == HealthStatus.Healthy && runtimeStatus == "Online";
        return isHealthy ? Results.Ok(new { status = "Healthy", checks = entries, timestamp = DateTimeOffset.UtcNow })
            : Results.Ok(new { status = "Degraded", checks = entries, timestamp = DateTimeOffset.UtcNow });
    }
}
