using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Yavsc.Blogspot;
namespace Yavsc.Api.Client;
///
/// High-level client for the Blog subsystem of the Yavsc API
/// (deployed at https://blogs.pschneider.fr). All transport
/// concerns — base URL, JSON serialisation, Bearer auth, silent
/// refresh on 401, request body shaping — are delegated to
/// , which lives in the consuming
/// application (PostIt). This class is a thin DTO↔path mapper,
/// nothing more.
///
/// URL convention. 's
/// BaseAddress already terminates with /api/v1/
/// (see Settings.ApiUrl). The path prefix below is
/// therefore relative to that version segment: a prefix of
/// "blog" resolves to …/api/v1/blog, which matches
/// the [Route(APIPrefix + "/blog")] attribute on
/// Yavsc.Blogs.Controllers.BlogApiController. Do not
/// re-include the api/ segment here — that produced 404s
/// in the past (see commit "PostIt: fix blog API double-prefix").
///
/// The class is intentionally non-IDisposable: it does not own the
/// it depends on. Lifetimes are managed
/// by the consumer (typically a singleton service registered with
/// the application).
///
public sealed class BlogApiClient
{
private const string DefaultPathPrefix = "blog";
private readonly IYavscApiClient _api;
private readonly Uri _baseAddress;
private readonly string _pathPrefix;
public BlogApiClient(IYavscApiClient api, string blogsBaseAddress, string pathPrefix = DefaultPathPrefix)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
if (string.IsNullOrEmpty(blogsBaseAddress))
throw new ArgumentException("Base address is required.", nameof(blogsBaseAddress));
// e.g. "https://blogs.pschneider.fr/api/v1/" — keep the
// trailing slash so relative paths ("posts") resolve correctly.
_baseAddress = new Uri(blogsBaseAddress);
api.Http.BaseAddress = _baseAddress;
_pathPrefix = pathPrefix?.TrimStart('/') ?? DefaultPathPrefix;
}
public Task> GetPostsAsync(int start = 0, int take = 25, CancellationToken ct = default)
=> _api.CallAsync>(
HttpMethod.Get,
$"{_pathPrefix}?start={start}&take={take}",
ct: ct);
public Task GetPostAsync(long id, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Get, $"{_pathPrefix}/{id}", ct: ct);
public Task CreatePostAsync(BlogPost post, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Post, _pathPrefix, body: post, ct: ct);
public Task UpdatePostAsync(long id, BlogPost post, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Put, $"{_pathPrefix}/{id}", body: post, ct: ct);
public Task DeletePostAsync(long id, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Delete, $"{_pathPrefix}/{id}", ct: ct);
}