using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
namespace XafPet.Desktop.PetEngine;
/// CFC 后端 API 客户端。所有接口统一 POST + JWT Bearer。
public sealed class ApiClient
{
private readonly HttpClient _http;
private readonly string _baseUrl;
private string _token;
private static readonly JsonSerializerOptions JsonOpts = new(JsonSerializerDefaults.Web);
public ApiClient(HttpClient http, string baseUrl, string token)
{
_http = http;
_baseUrl = baseUrl.TrimEnd('/');
_token = token;
}
public void UpdateToken(string token) => _token = token;
private async Task PostAsync(string path, object? body = null)
{
using var req = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}{path}");
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);
if (body != null)
{
req.Content = new StringContent(JsonSerializer.Serialize(body, JsonOpts),
Encoding.UTF8, "application/json");
}
var resp = await _http.SendAsync(req);
var json = await resp.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize>(json, JsonOpts)
?? throw new ApiException(-1, "响应解析失败");
if (!result.IsSuccess)
throw new ApiException(result.Code, result.Message ?? "未知错误");
return result.Data;
}
/// POST /api/tasks/today — 今日任务
public Task?> GetTodayTasksAsync()
=> PostAsync>("/api/tasks/today", new Dictionary());
/// POST /api/energy/overview — 五维能量概览
public Task GetEnergyOverviewAsync()
=> PostAsync("/api/energy/overview");
/// POST /api/daily/checkin — 今日打卡状态
public Task GetDailyCheckinAsync()
=> PostAsync("/api/daily/checkin");
/// POST /api/daily/checkin — 完成喝水打卡(body: {"type":"water"})
public async Task?> CompleteDrinkWaterAsync()
{
using var req = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/api/daily/checkin");
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);
req.Content = new StringContent("""{"type":"water"}""", Encoding.UTF8, "application/json");
var resp = await _http.SendAsync(req);
var json = await resp.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize>(json, JsonOpts)
?? throw new ApiException(-1, "响应解析失败");
if (!result.IsSuccess)
throw new ApiException(result.Code, result.Message ?? "未知错误");
return result;
}
/// POST /api/user/mascot/get — 获取用户已选吉祥物
public Task GetMascotAsync()
=> PostAsync("/api/user/mascot/get");
/// POST /api/user/mascot/set — 设置吉祥物
public Task