using System.Text.Json;
using System.Text.Json.Serialization;
using YandexMusic.API.Models.Common;

namespace YandexMusic.API.Common.Providers;

/// <summary>Базовый провайдер HTTP-запросов с общей логикой десериализации.</summary>
public abstract class CommonRequestProvider : IRequestProvider
{
    /// <summary>Хранилище данных авторизации.</summary>
    protected readonly AuthStorage storage;

    /// <summary>Настройки сериализации JSON (регистронезависимые, поддержка enum-строк).</summary>
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNameCaseInsensitive = true,
        Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
    };

    /// <summary>Инициализирует новый экземпляр провайдера.</summary>
    /// <param name="authStorage">Хранилище авторизации.</param>
    protected CommonRequestProvider(AuthStorage authStorage)
    {
        storage = authStorage;
    }

    /// <summary>Выполняет HTTP-запрос и возвращает ответ.</summary>
    public abstract Task<HttpResponseMessage> GetWebResponseAsync(
        HttpRequestMessage message,
        HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead);

    /// <summary>Преобразует HTTP-ответ в объект типа T.</summary>
    public virtual async Task<T> GetDataFromResponseAsync<T>(
        YandexMusicApi api,
        HttpResponseMessage response)
    {
        var json = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            var error = JsonSerializer.Deserialize<YErrorResponse>(json, JsonOptions);
            throw error ?? new Exception("Ошибка десериализации ответа с ошибкой.");
        }

        try
        {
            // Если нужен контекст выполнения, он добавляется через кастомный конвертер
            return JsonSerializer.Deserialize<T>(json, JsonOptions)
                ?? throw new JsonException("Десериализация вернула null");
        }
        catch (Exception ex)
        {
            throw new Exception($"Ошибка десериализации: {ex.Message}", ex);
        }
    }
}