using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using Nexus.Contracts.Devices;

namespace NexusShell.Agent;

public sealed class NexusApiClient
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
    };

    private readonly HttpClient _httpClient;
    private readonly NexusAgentConfig _config;

    public NexusApiClient(HttpClient httpClient, NexusAgentConfig config)
    {
        _httpClient = httpClient;
        _config = config;
    }

    public async Task<bool> RegisterDeviceAsync(DeviceRegistrationRequest request, CancellationToken cancellationToken = default)
    {
        var url = $"{_config.BackendUrl.TrimEnd('/')}/api/devices/register";
        try
        {
            using var response = await _httpClient.PostAsJsonAsync(url, request, JsonOptions, cancellationToken);
            if (response.IsSuccessStatusCode)
            {
                NexusAgentLogger.Info("registration", $"Device {request.DeviceId} registered at {url}");
                return true;
            }

            var body = await response.Content.ReadAsStringAsync(cancellationToken);
            NexusAgentLogger.Warn("registration", $"Backend returned {(int)response.StatusCode}: {body}");
            return false;
        }
        catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException)
        {
            NexusAgentLogger.Warn("registration", $"Backend unavailable at {url}");
            return false;
        }
        catch (Exception ex)
        {
            NexusAgentLogger.Error("registration", "Registration failed", ex);
            return false;
        }
    }

    public async Task<bool> SendHeartbeatAsync(DeviceHeartbeatRequest request, CancellationToken cancellationToken = default)
    {
        var url = $"{_config.BackendUrl.TrimEnd('/')}/api/devices/heartbeat";
        try
        {
            using var response = await _httpClient.PostAsJsonAsync(url, request, JsonOptions, cancellationToken);
            if (response.IsSuccessStatusCode)
            {
                return true;
            }

            NexusAgentLogger.Warn("heartbeat", $"Backend heartbeat returned {(int)response.StatusCode}");
            return false;
        }
        catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException)
        {
            NexusAgentLogger.Warn("heartbeat", "Backend unavailable for heartbeat");
            return false;
        }
        catch (Exception ex)
        {
            NexusAgentLogger.Error("heartbeat", "Heartbeat failed", ex);
            return false;
        }
    }
}
