using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NexusReader.Application.Common;
using NexusReader.Application.Queries.Recommendations;
using NexusReader.UI.Shared.Services;

namespace NexusReader.Web.Client.Services;

/// <summary>
/// WASM implementation of <see cref="IRecommendationService"/> that fetches contextual recommendations
/// from the <c>/api/recommendations</c> server endpoint via a named <c>NexusAPI</c> HTTP client.
/// </summary>
internal sealed class RecommendationService : IRecommendationService
{
    private readonly HttpClient _http;
    private readonly ILogger<RecommendationService> _logger;

    /// <summary>
    /// Initializes a new instance of <see cref="RecommendationService"/>.
    /// </summary>
    public RecommendationService(HttpClient http, ILogger<RecommendationService> logger)
    {
        _http = http;
        _logger = logger;
    }

    /// <inheritdoc />
    public async Task<List<RecommendationDto>?> GetRecommendationsAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            var response = await _http.GetAsync("/api/recommendations", cancellationToken);

            if (response.StatusCode == HttpStatusCode.NoContent || response.StatusCode == HttpStatusCode.NotFound)
            {
                _logger.LogInformation("[RecommendationService] No recommendations available (status {StatusCode}).", response.StatusCode);
                return new List<RecommendationDto>();
            }

            response.EnsureSuccessStatusCode();

            var result = await response.Content.ReadFromJsonAsync(
                AppJsonContext.Default.ContextualRecommendationResponse,
                cancellationToken);

            if (result is null)
            {
                _logger.LogWarning("[RecommendationService] Deserialised response was null.");
                return new List<RecommendationDto>();
            }

            _logger.LogInformation("[RecommendationService] Received {Count} recommendations.", result.Recommendations.Count);
            return result.Recommendations;
        }
        catch (HttpRequestException httpEx)
        {
            _logger.LogError(httpEx, "[RecommendationService] HTTP error fetching recommendations: {Message}", httpEx.Message);
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[RecommendationService] Unexpected error fetching recommendations.");
            return null;
        }
    }
}
