using InboxIntel.Application.Common; using InboxIntel.Application.DTOs; using InboxIntel.Domain.Enums; namespace InboxIntel.Application.Abstractions; /// Orchestrates full + incremental Gmail sync, with resume support. public interface ISyncService { Task RunFullSyncAsync(Guid userId, CancellationToken ct = default); Task RunIncrementalSyncAsync(Guid userId, CancellationToken ct = default); /// Marks the sync as starting and queues it for the background worker. Task QueueSyncAsync(Guid userId, bool fullSync, CancellationToken ct = default); Task GetStatusAsync(Guid userId, CancellationToken ct = default); /// Progress snapshot for the sync splash screen. Task GetProgressAsync(Guid userId, CancellationToken ct = default); } public interface IAnalyticsService { Task GetDashboardAsync(Guid userId, CancellationToken ct = default); Task GetInboxHealthAsync(Guid userId, CancellationToken ct = default); Task> GetTopSendersAsync(Guid userId, int take = 20, CancellationToken ct = default); Task> GetVolumeOverTimeAsync(Guid userId, int days = 90, CancellationToken ct = default); Task> GetHeatmapAsync(Guid userId, CancellationToken ct = default); Task> GetCategoryHeatmapAsync(Guid userId, CancellationToken ct = default); Task> GetAttachmentBreakdownAsync(Guid userId, CancellationToken ct = default); Task GetSidebarCountsAsync(Guid userId, CancellationToken ct = default); Task RefreshAggregatesAsync(Guid userId, CancellationToken ct = default); } public interface ISearchService { Task> SearchAsync(Guid userId, SearchRequestDto request, CancellationToken ct = default); } public interface ICleanupService { Task PreviewAsync(Guid userId, CleanupRequestDto request, CancellationToken ct = default); Task> ExecuteAsync(Guid userId, CleanupRequestDto request, CancellationToken ct = default); } public interface IUnsubscribeService { Task> GetSafeToUnsubscribeAsync(Guid userId, CancellationToken ct = default); Task DetectAsync(Guid userId, CancellationToken ct = default); Task> ProcessQueueAsync(Guid userId, UnsubscribeRequestDto request, CancellationToken ct = default); } /// /// AI layer. May be disabled, local (Ollama) or cloud (OpenAI). Per the /// safety rules, AI NEVER executes destructive actions - it only suggests. /// public interface IAiService { bool IsEnabled { get; } Task ClassifyAsync(Guid userId, Guid emailId, CancellationToken ct = default); /// /// Lightweight classification used as a sync-time fallback when the /// heuristic rule set doesn't match anything specific. Takes raw fields /// directly (no DB lookup) since the email entity may not be persisted /// yet during sync. /// Task ClassifyFallbackAsync(string? subject, string senderAddress, string? snippet, CancellationToken ct = default); /// /// AI opinion (0-1) on how safe it is to unsubscribe from a sender, given /// the sender address and a recent subject line. Returns 0.5 (neutral) if /// AI is disabled or the call fails - callers blend this with a heuristic. /// Task ScoreUnsubscribeConfidenceAsync(string senderAddress, string? recentSubject, int emailCount, CancellationToken ct = default); /// One-line plain-language summary of a single email, for list/preview UIs. Task SummarizeEmailAsync(string? subject, string? snippet, string? bodyText, CancellationToken ct = default); Task SummarizeInboxAsync(Guid userId, CancellationToken ct = default); Task> SuggestCleanupAsync(Guid userId, CancellationToken ct = default); Task GenerateQueryAsync(Guid userId, string naturalLanguage, CancellationToken ct = default); } /// Low-level chat completion abstraction implemented by Ollama / OpenAI providers. public interface IAiProvider { AiProviderMode Mode { get; } Task CompleteAsync(string systemPrompt, string userPrompt, CancellationToken ct = default); } /// /// Produces vector embeddings for text (the foundation for semantic search, near-duplicate /// detection, and "find similar"). Kept separate from because /// embeddings are a distinct capability with their own model. The Null implementation returns /// an empty vector and = false, so callers detect unavailability and /// fall back to lexical search — AI is never required for core functionality. /// public interface IEmbeddingProvider { /// False for the Null provider (AI off / no embedding model configured). bool IsAvailable { get; } /// Embed a single text. Returns an empty array when unavailable. Task EmbedAsync(string text, CancellationToken ct = default); /// Embed many texts, result aligned to input order. Empty list when unavailable. Task> EmbedBatchAsync(IReadOnlyList texts, CancellationToken ct = default); } public enum ExportFormat { Pdf, Csv, Json } public interface IExportService { Task<(byte[] Content, string ContentType, string FileName)> ExportReportAsync(Guid userId, ExportFormat format, CancellationToken ct = default); } /// SMTP-backed email delivery, used for digest notifications. No-ops if SMTP is not configured. public interface IEmailSender { bool IsEnabled { get; } Task SendAsync(string toAddress, string subject, string htmlBody, CancellationToken ct = default); } /// Builds and sends the periodic inbox digest for opted-in users. public interface IDigestService { Task SendDigestAsync(Guid userId, CancellationToken ct = default); }