using System.Text.Json.Serialization; namespace ChangeT50.Agent; public sealed record AgentOptions( Uri BaseUrl, string ProviderCode, string DeviceId, string Secret, string Mode, string JournalPath, string? DllPath, string? WebServiceUrl, int TerminalId, int UploadMessageBufferBytes); public sealed class ApiEnvelope { public int Code { get; init; } public string Message { get; init; } = string.Empty; public T? Data { get; init; } public string TraceId { get; init; } = string.Empty; } public sealed class TaskListData { public List Tasks { get; init; } = []; } public sealed class AgentTask { public long TaskId { get; init; } public string ClientOrderNo { get; init; } = string.Empty; public string TaskType { get; init; } = string.Empty; public long AmountCents { get; init; } public string WalletCode { get; init; } = string.Empty; public string PersonExternalNo { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; public string LeaseUntil { get; init; } = string.Empty; public string ProviderTradeNo { get; init; } = string.Empty; public int RetryCount { get; init; } public string RecoveryAction { get; init; } = string.Empty; public Dictionary Payload { get; init; } = []; } public sealed class AcceptanceData { public bool Idempotent { get; init; } public string ClientOrderNo { get; init; } = string.Empty; public string LeaseToken { get; init; } = string.Empty; public string LeaseUntil { get; init; } = string.Empty; public AgentTask Task { get; init; } = new(); } public sealed class PersonData { public bool Found { get; init; } public string ExternalNo { get; init; } = string.Empty; public string StaffUuid { get; init; } = string.Empty; public string Name { get; init; } = string.Empty; public string DepartmentCode { get; init; } = string.Empty; public string Status { get; init; } = string.Empty; public string AccountType { get; init; } = string.Empty; public string OneCardAccountNo { get; init; } = string.Empty; public string CardNoMasked { get; init; } = string.Empty; public string UpdatedAt { get; init; } = string.Empty; } public sealed class ConsumeExecution { public string ClientOrderNo { get; init; } = string.Empty; public long AmountCents { get; init; } public string Result { get; init; } = "unknown"; public string ResultCode { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; public string CardNoHash { get; init; } = string.Empty; public string CardNoMasked { get; init; } = string.Empty; public long OpCountAfter { get; init; } public string PsamTradeNo { get; init; } = string.Empty; public string Tac { get; init; } = string.Empty; public DateTimeOffset OccurredAt { get; init; } = DateTimeOffset.Now; // Persisted only in the Agent's local journal so an already-debited card can // be uploaded after restart without touching the physical card again. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public NativeUploadPayload? NativeUpload { get; init; } } public sealed class NativeUploadPayload { public int TerminalId { get; init; } public int WalletNumber { get; init; } public DateTime TradeTime { get; init; } public long PsamId { get; init; } public int PsamTradeNumber { get; init; } public int Tac { get; init; } public NativeCardSnapshot Before { get; init; } = new(); public NativeCardSnapshot After { get; init; } = new(); } public sealed class NativeCardSnapshot { public int CardClass { get; init; } public int CustomerId { get; init; } public int CardNumber { get; init; } public int CardSerialNumber { get; init; } public int TotalAmountCents { get; init; } public int MainWalletBalanceCents { get; init; } public int MainWalletOperationCount { get; init; } public int SubsidyWalletBalanceCents { get; init; } public int SubsidyWalletOperationCount { get; init; } public string CardAsnBase64 { get; init; } = string.Empty; } public sealed class UploadExecution { public string Result { get; init; } = "unknown"; public string ResultCode { get; init; } = string.Empty; public string Message { get; init; } = string.Empty; public string ProviderTradeNo { get; init; } = string.Empty; public int RetryCount { get; init; } public long? BalanceBeforeCents { get; init; } public long? BalanceAfterCents { get; init; } } public sealed class HealthSnapshot { public string Status { get; init; } = "online"; public string AgentVersion { get; init; } = "1.0.0"; public string DllVersion { get; init; } = string.Empty; public string ReaderStatus { get; init; } = "unknown"; public string PsamStatus { get; init; } = "unknown"; public int PendingUploadCount { get; init; } } public sealed class JournalEntry { public string ClientOrderNo { get; init; } = string.Empty; public string LeaseToken { get; set; } = string.Empty; public string State { get; set; } = "accepted"; public ConsumeExecution? Consume { get; set; } public UploadExecution? Upload { get; set; } public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.Now; }