using Refit; namespace OTSSignsOrchestrator.Desktop.Services; // ── DTOs matching server REST API responses ───────────────────────────────── public record FleetSummaryDto { public Guid CustomerId { get; init; } public string Abbreviation { get; init; } = string.Empty; public string CompanyName { get; init; } = string.Empty; public string Plan { get; init; } = string.Empty; public int ScreenCount { get; init; } public string HealthStatus { get; init; } = "Unknown"; public DateTime? LastHealthCheck { get; init; } public bool HasRunningJob { get; init; } } public record CustomerDetailDto { public Guid Id { get; init; } public string Abbreviation { get; init; } = string.Empty; public string CompanyName { get; init; } = string.Empty; public string? AdminEmail { get; init; } public string Plan { get; init; } = string.Empty; public int ScreenCount { get; init; } public string Status { get; init; } = string.Empty; public DateTime CreatedAt { get; init; } public List Instances { get; init; } = []; public List ActiveJobs { get; init; } = []; } public record CustomerInstanceDto { public Guid Id { get; init; } public string? XiboUrl { get; init; } public string? DockerStackName { get; init; } public string HealthStatus { get; init; } = "Unknown"; public DateTime? LastHealthCheck { get; init; } } public record CustomerJobDto { public Guid Id { get; init; } public string JobType { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; public DateTime CreatedAt { get; init; } public DateTime? StartedAt { get; init; } } public record CreateJobRequest(Guid CustomerId, string JobType, string? Parameters); public record CreateJobResponse { public Guid Id { get; init; } public string JobType { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; } public record JobDetailDto { public Guid Id { get; init; } public Guid CustomerId { get; init; } public string JobType { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; public string? TriggeredBy { get; init; } public string? Parameters { get; init; } public DateTime CreatedAt { get; init; } public DateTime? StartedAt { get; init; } public DateTime? CompletedAt { get; init; } public string? ErrorMessage { get; init; } public List Steps { get; init; } = []; } public record JobStepDto { public Guid Id { get; init; } public string StepName { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; public string? LogOutput { get; init; } public DateTime? StartedAt { get; init; } public DateTime? CompletedAt { get; init; } } public record LoginRequest(string Email, string Password); public record RefreshRequest(string RefreshToken); public record AuthResponse { public string Token { get; init; } = string.Empty; public string RefreshToken { get; init; } = string.Empty; } public record RefreshResponse { public string Token { get; init; } = string.Empty; } // ── Refit interface ───────────────────────────────────────────────────────── [Headers("Accept: application/json")] public interface IServerApiClient { [Get("/api/fleet")] Task> GetFleetAsync(); [Get("/api/fleet/{id}")] Task GetCustomerDetailAsync(Guid id); [Post("/api/jobs")] Task CreateJobAsync([Body] CreateJobRequest body); [Get("/api/jobs/{id}")] Task GetJobAsync(Guid id); [Post("/api/auth/login")] Task LoginAsync([Body] LoginRequest body); [Post("/api/auth/refresh")] Task RefreshAsync([Body] RefreshRequest body); [Get("/api/reports/billing")] Task GetBillingCsvAsync([Query] DateOnly from, [Query] DateOnly to); [Get("/api/reports/fleet-health")] Task GetFleetHealthPdfAsync(); [Post("/api/fleet/bulk/{action}")] Task BulkActionAsync(string action); } // ── DelegatingHandler for Bearer token injection ──────────────────────────── public class AuthHeaderHandler : DelegatingHandler { private readonly TokenStoreService _tokenStore; public AuthHeaderHandler(TokenStoreService tokenStore) { _tokenStore = tokenStore; } protected override async Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var jwt = _tokenStore.GetJwt(); if (!string.IsNullOrEmpty(jwt)) request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt); return await base.SendAsync(request, cancellationToken); } }