using System.Net.Http.Headers;
using System.Text.Json;

namespace TeleWave.Infrastructure.Metadata;

/// <summary>Общие для провайдеров метаданных хелперы: HTTP-загрузка JSON и чтение полей.</summary>
internal static class MetadataJson
{
    /// <summary>
    /// GET+parse через клиент "metadata"; бросает при не-2xx/сетевой ошибке (для поиска — показать
    /// сбой). <paramref name="bearerToken"/> задаётся, когда источник авторизует не ключом в query,
    /// а заголовком (у TMDb так работает токен v4).
    /// </summary>
    public static async Task<JsonDocument> GetAsync(
        IHttpClientFactory httpFactory,
        string url,
        CancellationToken cancellationToken,
        string? bearerToken = null
    )
    {
        var client = httpFactory.CreateClient("metadata");
        using var request = new HttpRequestMessage(HttpMethod.Get, url);
        if (!string.IsNullOrEmpty(bearerToken))
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
        using var response = await client.SendAsync(request, cancellationToken);
        response.EnsureSuccessStatusCode();
        var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
        return await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
    }

    /// <summary>Как <see cref="GetAsync"/>, но глотает ошибки в null (для get/episode — деградируем мягко).</summary>
    public static async Task<JsonDocument?> TryGetAsync(
        IHttpClientFactory httpFactory,
        string url,
        CancellationToken cancellationToken,
        string? bearerToken = null
    )
    {
        try
        {
            return await GetAsync(httpFactory, url, cancellationToken, bearerToken);
        }
        catch (Exception ex)
            when (ex is HttpRequestException or JsonException or TaskCanceledException)
        {
            return null;
        }
    }

    public static string? GetString(JsonElement el, string name) =>
        el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String
            ? v.GetString()
            : null;

    public static int? GetInt(JsonElement el, string name) =>
        el.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.Number
            ? v.GetInt32()
            : null;

    /// <summary>Год из первых 4 символов строки даты/года ("YYYY-MM-DD" или "YYYY").</summary>
    public static int? YearFrom(string? value) =>
        value is { Length: >= 4 } && int.TryParse(value.AsSpan(0, 4), out var y) ? y : null;
}
