using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Yavsc.Api.Client.Dtos;
namespace Yavsc.Api.Client;
///
/// HTTP client for /api/circle on the Yavsc Blogs server.
///
/// Same conventions as : all
/// transport is delegated to ; this
/// class only maps paths to DTOs.
///
/// The server now (since the BlogAcl fix on this branch)
/// scopes every read and write to the caller's uid. There is no
/// way for the client to read or modify another user's circles
/// — the route will return 404 (not 403) when the circle exists
/// but belongs to someone else, to avoid leaking its existence.
///
public sealed class CircleApiClient
{
private const string Path = "circle";
private readonly IYavscApiClient _api;
public CircleApiClient(IYavscApiClient api, string blogsBaseAddress)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
if (string.IsNullOrEmpty(blogsBaseAddress))
throw new ArgumentException("Base address is required.", nameof(blogsBaseAddress));
if (api.Http.BaseAddress is null)
api.Http.BaseAddress = new Uri(blogsBaseAddress);
}
public Task> GetMyCirclesAsync(CancellationToken ct = default)
=> _api.CallAsync>(HttpMethod.Get, Path, ct: ct);
public Task GetCircleAsync(long id, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Get, $"{Path}/{id}", ct: ct);
public Task CreateCircleAsync(CircleDto circle, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Post, Path, body: circle, ct: ct);
public Task UpdateCircleAsync(long id, CircleDto circle, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Put, $"{Path}/{id}", body: circle, ct: ct);
public Task DeleteCircleAsync(long id, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Delete, $"{Path}/{id}", ct: ct);
///
/// Returns the members of one of the caller's circles.
/// Returns null when the circle does not exist or is not
/// owned by the caller (the server scopes the endpoint
/// with a 404 in either case to avoid leaking existence
/// — this client flattens that into a null result).
///
public Task?> GetMembersAsync(long id, CancellationToken ct = default)
=> _api.CallAsync?>(HttpMethod.Get, $"{Path}/{id}/members", ct: ct);
///
/// Adds a Yavsc user (resolved client-side via
/// /api/user-search) to one of the caller's
/// circles. Returns null when the circle does not exist
/// or is not owned by the caller, or when the target
/// user does not exist. Throws on 409 (already a
/// member) — callers that want idempotent behaviour
/// can swallow the exception or dedupe beforehand.
///
public Task AddMemberAsync(long id, string userId, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Post, $"{Path}/{id}/members",
body: new { userId }, ct: ct);
///
/// Removes a user from one of the caller's circles.
/// Returns null on success (the server returns 200 OK
/// with no body) or when the membership does not
/// exist — both treated as success by the caller.
///
public Task RemoveMemberAsync(long id, string userId, CancellationToken ct = default)
=> _api.CallAsync(HttpMethod.Delete, $"{Path}/{id}/members/{userId}", ct: ct);
}