using System.Text.Json; namespace Tiku.Application.Growth; public sealed record CrmAdminActor(Guid TenantId, Guid UserId); public sealed record UpsertCrmConfigCommand( bool Enabled, string? Url, string? SecretRef, string? Secret, string? FormName, string? ExamType, int? TimeoutSeconds, int? DelaySeconds, string? AssignmentMode, JsonElement? AssignmentPool, JsonElement? AssignmentConfig); public sealed record CrmQueueQuery(string? Status = null, Guid? QueueId = null, string? Source = null, int? Limit = null); public sealed record CrmQueueLogQuery(Guid? QueueId = null, int? Limit = null); public sealed record CrmQueueActionCommand(Guid QueueId, string? Action, string? Note, JsonElement? Metadata); public sealed record CrmConfigItem( Guid Id, bool Enabled, string? Url, string? SecretRef, string AssignmentMode, JsonElement AssignmentPool, string? FormName, string? ExamType, int? TimeoutSeconds, int? DelaySeconds, DateTimeOffset UpdatedAt); public sealed record CrmQueueItem( Guid Id, string Status, int Attempts, string? LeadId, string? RecordId, string? Source, string? Provider, string? LastError, DateTimeOffset? ScheduledAt, DateTimeOffset? NextAttemptAt, JsonElement Payload); public sealed record CrmQueueLogItem( Guid Id, Guid? QueueId, string? RecordId, string? LeadId, int? HttpCode, string Outcome, string? ErrorMessage, string? Operation, JsonElement RequestPayload, string? ResponseSummary, DateTimeOffset CreatedAt); public sealed record CrmDeadLetterSummary(int Failed, int Discarded, int Total, DateTimeOffset? OldestOpenAt); public sealed record CrmDeadLetterResult(CrmDeadLetterSummary Summary, IReadOnlyCollection Items); public sealed record CrmList(IReadOnlyCollection Items); public interface ICrmService { Task GetConfigAsync(CrmAdminActor actor, CancellationToken cancellationToken = default); Task UpsertConfigAsync( CrmAdminActor actor, UpsertCrmConfigCommand command, CancellationToken cancellationToken = default); Task> GetQueueAsync( CrmAdminActor actor, CrmQueueQuery query, CancellationToken cancellationToken = default); Task GetDeadLettersAsync( CrmAdminActor actor, CrmQueueQuery query, CancellationToken cancellationToken = default); Task> GetLogsAsync( CrmAdminActor actor, CrmQueueLogQuery query, CancellationToken cancellationToken = default); Task ApplyQueueActionAsync( CrmAdminActor actor, CrmQueueActionCommand command, CancellationToken cancellationToken = default); } public sealed class CrmException(string message, string code) : Exception(message) { public string Code { get; } = code; }