using System; using System.Collections.Generic; using System.Text.Json.Serialization; namespace StellaOps.Cli.Services.Models; // CLI-PARITY-41-002: Notify command models for CLI /// /// Notify channel types. /// [JsonConverter(typeof(JsonStringEnumConverter))] internal enum NotifyChannelType { Slack, Teams, Email, Webhook, Custom, PagerDuty, OpsGenie, Cli, InAppInbox, InApp } /// /// Notify delivery status. /// [JsonConverter(typeof(JsonStringEnumConverter))] internal enum NotifyDeliveryStatus { Pending, Sent, Failed, Throttled, Digested, Dropped } /// /// Notify channel list request. /// internal sealed class NotifyChannelListRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("type")] public string? Type { get; init; } [JsonPropertyName("enabled")] public bool? Enabled { get; init; } [JsonPropertyName("limit")] public int? Limit { get; init; } [JsonPropertyName("offset")] public int? Offset { get; init; } [JsonPropertyName("cursor")] public string? Cursor { get; init; } } /// /// Notify channel list response. /// internal sealed class NotifyChannelListResponse { [JsonPropertyName("items")] public IReadOnlyList Items { get; init; } = []; [JsonPropertyName("total")] public int Total { get; init; } [JsonPropertyName("hasMore")] public bool HasMore { get; init; } [JsonPropertyName("nextCursor")] public string? NextCursor { get; init; } } /// /// Notify channel summary for list view. /// internal sealed class NotifyChannelSummary { [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("name")] public string Name { get; init; } = string.Empty; [JsonPropertyName("displayName")] public string? DisplayName { get; init; } [JsonPropertyName("type")] public string Type { get; init; } = string.Empty; [JsonPropertyName("enabled")] public bool Enabled { get; init; } [JsonPropertyName("createdAt")] public DateTimeOffset CreatedAt { get; init; } [JsonPropertyName("updatedAt")] public DateTimeOffset UpdatedAt { get; init; } [JsonPropertyName("deliveryCount")] public int DeliveryCount { get; init; } [JsonPropertyName("failureRate")] public double? FailureRate { get; init; } } /// /// Detailed notify channel response. /// internal sealed class NotifyChannelDetail { [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("tenantId")] public string TenantId { get; init; } = string.Empty; [JsonPropertyName("name")] public string Name { get; init; } = string.Empty; [JsonPropertyName("displayName")] public string? DisplayName { get; init; } [JsonPropertyName("description")] public string? Description { get; init; } [JsonPropertyName("type")] public string Type { get; init; } = string.Empty; [JsonPropertyName("enabled")] public bool Enabled { get; init; } [JsonPropertyName("config")] public NotifyChannelConfigInfo? Config { get; init; } [JsonPropertyName("labels")] public IReadOnlyDictionary? Labels { get; init; } [JsonPropertyName("metadata")] public IReadOnlyDictionary? Metadata { get; init; } [JsonPropertyName("createdBy")] public string? CreatedBy { get; init; } [JsonPropertyName("createdAt")] public DateTimeOffset CreatedAt { get; init; } [JsonPropertyName("updatedBy")] public string? UpdatedBy { get; init; } [JsonPropertyName("updatedAt")] public DateTimeOffset UpdatedAt { get; init; } [JsonPropertyName("stats")] public NotifyChannelStats? Stats { get; init; } [JsonPropertyName("health")] public NotifyChannelHealth? Health { get; init; } } /// /// Notify channel configuration info (redacted secrets). /// internal sealed class NotifyChannelConfigInfo { [JsonPropertyName("secretRef")] public string SecretRef { get; init; } = string.Empty; [JsonPropertyName("target")] public string? Target { get; init; } [JsonPropertyName("endpoint")] public string? Endpoint { get; init; } [JsonPropertyName("properties")] public IReadOnlyDictionary? Properties { get; init; } [JsonPropertyName("limits")] public NotifyChannelLimitsInfo? Limits { get; init; } } /// /// Notify channel limits. /// internal sealed class NotifyChannelLimitsInfo { [JsonPropertyName("concurrency")] public int? Concurrency { get; init; } [JsonPropertyName("requestsPerMinute")] public int? RequestsPerMinute { get; init; } [JsonPropertyName("timeoutSeconds")] public int? TimeoutSeconds { get; init; } [JsonPropertyName("maxBatchSize")] public int? MaxBatchSize { get; init; } } /// /// Notify channel statistics. /// internal sealed class NotifyChannelStats { [JsonPropertyName("totalDeliveries")] public long TotalDeliveries { get; init; } [JsonPropertyName("successfulDeliveries")] public long SuccessfulDeliveries { get; init; } [JsonPropertyName("failedDeliveries")] public long FailedDeliveries { get; init; } [JsonPropertyName("throttledDeliveries")] public long ThrottledDeliveries { get; init; } [JsonPropertyName("lastDeliveryAt")] public DateTimeOffset? LastDeliveryAt { get; init; } [JsonPropertyName("avgLatencyMs")] public double? AvgLatencyMs { get; init; } } /// /// Notify channel health status. /// internal sealed class NotifyChannelHealth { [JsonPropertyName("status")] public string Status { get; init; } = string.Empty; [JsonPropertyName("lastCheckAt")] public DateTimeOffset? LastCheckAt { get; init; } [JsonPropertyName("consecutiveFailures")] public int ConsecutiveFailures { get; init; } [JsonPropertyName("errorMessage")] public string? ErrorMessage { get; init; } } /// /// Channel test request. /// internal sealed class NotifyChannelTestRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("message")] public string? Message { get; init; } } /// /// Channel test result. /// internal sealed class NotifyChannelTestResult { [JsonPropertyName("success")] public bool Success { get; init; } [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("latencyMs")] public long? LatencyMs { get; init; } [JsonPropertyName("responseCode")] public int? ResponseCode { get; init; } [JsonPropertyName("errorMessage")] public string? ErrorMessage { get; init; } [JsonPropertyName("deliveryId")] public string? DeliveryId { get; init; } } /// /// Notify rule list request. /// internal sealed class NotifyRuleListRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("enabled")] public bool? Enabled { get; init; } [JsonPropertyName("eventType")] public string? EventType { get; init; } [JsonPropertyName("channelId")] public string? ChannelId { get; init; } [JsonPropertyName("limit")] public int? Limit { get; init; } [JsonPropertyName("offset")] public int? Offset { get; init; } } /// /// Notify rule list response. /// internal sealed class NotifyRuleListResponse { [JsonPropertyName("items")] public IReadOnlyList Items { get; init; } = []; [JsonPropertyName("total")] public int Total { get; init; } [JsonPropertyName("hasMore")] public bool HasMore { get; init; } } /// /// Notify rule summary. /// internal sealed class NotifyRuleSummary { [JsonPropertyName("ruleId")] public string RuleId { get; init; } = string.Empty; [JsonPropertyName("name")] public string Name { get; init; } = string.Empty; [JsonPropertyName("description")] public string? Description { get; init; } [JsonPropertyName("enabled")] public bool Enabled { get; init; } [JsonPropertyName("eventTypes")] public IReadOnlyList EventTypes { get; init; } = []; [JsonPropertyName("channelIds")] public IReadOnlyList ChannelIds { get; init; } = []; [JsonPropertyName("priority")] public int Priority { get; init; } [JsonPropertyName("matchCount")] public long MatchCount { get; init; } } /// /// Notify delivery list request. /// internal sealed class NotifyDeliveryListRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("channelId")] public string? ChannelId { get; init; } [JsonPropertyName("status")] public string? Status { get; init; } [JsonPropertyName("eventType")] public string? EventType { get; init; } [JsonPropertyName("since")] public DateTimeOffset? Since { get; init; } [JsonPropertyName("until")] public DateTimeOffset? Until { get; init; } [JsonPropertyName("limit")] public int? Limit { get; init; } [JsonPropertyName("cursor")] public string? Cursor { get; init; } } /// /// Notify delivery list response. /// internal sealed class NotifyDeliveryListResponse { [JsonPropertyName("items")] public IReadOnlyList Items { get; init; } = []; [JsonPropertyName("total")] public int Total { get; init; } [JsonPropertyName("hasMore")] public bool HasMore { get; init; } [JsonPropertyName("nextCursor")] public string? NextCursor { get; init; } } /// /// Notify delivery summary. /// internal sealed class NotifyDeliverySummary { [JsonPropertyName("deliveryId")] public string DeliveryId { get; init; } = string.Empty; [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("channelName")] public string? ChannelName { get; init; } [JsonPropertyName("channelType")] public string ChannelType { get; init; } = string.Empty; [JsonPropertyName("eventType")] public string EventType { get; init; } = string.Empty; [JsonPropertyName("status")] public string Status { get; init; } = string.Empty; [JsonPropertyName("attemptCount")] public int AttemptCount { get; init; } [JsonPropertyName("createdAt")] public DateTimeOffset CreatedAt { get; init; } [JsonPropertyName("sentAt")] public DateTimeOffset? SentAt { get; init; } [JsonPropertyName("latencyMs")] public long? LatencyMs { get; init; } } /// /// Notify delivery detail. /// internal sealed class NotifyDeliveryDetail { [JsonPropertyName("deliveryId")] public string DeliveryId { get; init; } = string.Empty; [JsonPropertyName("tenantId")] public string TenantId { get; init; } = string.Empty; [JsonPropertyName("channelId")] public string ChannelId { get; init; } = string.Empty; [JsonPropertyName("channelName")] public string? ChannelName { get; init; } [JsonPropertyName("channelType")] public string ChannelType { get; init; } = string.Empty; [JsonPropertyName("ruleId")] public string? RuleId { get; init; } [JsonPropertyName("eventId")] public string? EventId { get; init; } [JsonPropertyName("eventType")] public string EventType { get; init; } = string.Empty; [JsonPropertyName("status")] public string Status { get; init; } = string.Empty; [JsonPropertyName("subject")] public string? Subject { get; init; } [JsonPropertyName("attemptCount")] public int AttemptCount { get; init; } [JsonPropertyName("attempts")] public IReadOnlyList? Attempts { get; init; } [JsonPropertyName("createdAt")] public DateTimeOffset CreatedAt { get; init; } [JsonPropertyName("sentAt")] public DateTimeOffset? SentAt { get; init; } [JsonPropertyName("failedAt")] public DateTimeOffset? FailedAt { get; init; } [JsonPropertyName("errorMessage")] public string? ErrorMessage { get; init; } [JsonPropertyName("idempotencyKey")] public string? IdempotencyKey { get; init; } } /// /// Notify delivery attempt. /// internal sealed class NotifyDeliveryAttempt { [JsonPropertyName("attemptNumber")] public int AttemptNumber { get; init; } [JsonPropertyName("status")] public string Status { get; init; } = string.Empty; [JsonPropertyName("attemptedAt")] public DateTimeOffset AttemptedAt { get; init; } [JsonPropertyName("latencyMs")] public long? LatencyMs { get; init; } [JsonPropertyName("responseCode")] public int? ResponseCode { get; init; } [JsonPropertyName("errorMessage")] public string? ErrorMessage { get; init; } } /// /// Retry delivery request. /// internal sealed class NotifyRetryRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("deliveryId")] public string DeliveryId { get; init; } = string.Empty; [JsonPropertyName("idempotencyKey")] public string? IdempotencyKey { get; init; } } /// /// Retry delivery result. /// internal sealed class NotifyRetryResult { [JsonPropertyName("success")] public bool Success { get; init; } [JsonPropertyName("deliveryId")] public string DeliveryId { get; init; } = string.Empty; [JsonPropertyName("newStatus")] public string? NewStatus { get; init; } [JsonPropertyName("errors")] public IReadOnlyList? Errors { get; init; } [JsonPropertyName("auditEventId")] public string? AuditEventId { get; init; } } /// /// Send notification request. /// internal sealed class NotifySendRequest { [JsonPropertyName("tenant")] public string? Tenant { get; init; } [JsonPropertyName("channelId")] public string? ChannelId { get; init; } [JsonPropertyName("eventType")] public string EventType { get; init; } = string.Empty; [JsonPropertyName("subject")] public string? Subject { get; init; } [JsonPropertyName("body")] public string Body { get; init; } = string.Empty; [JsonPropertyName("severity")] public string? Severity { get; init; } [JsonPropertyName("metadata")] public IReadOnlyDictionary? Metadata { get; init; } [JsonPropertyName("idempotencyKey")] public string? IdempotencyKey { get; init; } } /// /// Send notification result. /// internal sealed class NotifySendResult { [JsonPropertyName("success")] public bool Success { get; init; } [JsonPropertyName("eventId")] public string? EventId { get; init; } [JsonPropertyName("deliveryIds")] public IReadOnlyList? DeliveryIds { get; init; } [JsonPropertyName("channelsMatched")] public int ChannelsMatched { get; init; } [JsonPropertyName("errors")] public IReadOnlyList? Errors { get; init; } [JsonPropertyName("idempotencyKey")] public string? IdempotencyKey { get; init; } }