using System; using System.Threading.Tasks; using Serilog; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Synchronization; namespace Wino.Core.Synchronizers.Errors; /// /// Generic handler for 404 (Not Found) errors across all synchronizers. /// When a resource is already gone on the server, this handler applies /// the intended change locally instead of throwing. /// Works for all mail actions, folder actions, and batch operations. /// public class EntityNotFoundHandler : ISynchronizerErrorHandler { private readonly ILogger _logger = Log.ForContext(); private readonly IMailService _mailService; private readonly IFolderService _folderService; public EntityNotFoundHandler(IMailService mailService, IFolderService folderService) { _mailService = mailService; _folderService = folderService; } public bool CanHandle(SynchronizerErrorContext error) { if (error.ErrorCode != 404) return false; if (error.RequestBundle == null) return false; return true; } public async Task HandleAsync(SynchronizerErrorContext error) { error.Severity = SynchronizerErrorSeverity.Recoverable; error.Category = SynchronizerErrorCategory.ResourceNotFound; var uiRequest = error.RequestBundle.UIChangeRequest; // --- Folder actions --- if (uiRequest is IFolderActionRequest folderAction) { _logger.Warning("Entity not found (404) for folder operation {Op} on {RemoteFolderId}. Deleting locally.", folderAction.Operation, folderAction.Folder.RemoteFolderId); try { await _folderService.DeleteFolderAsync( folderAction.Folder.MailAccountId, folderAction.Folder.RemoteFolderId).ConfigureAwait(false); } catch (Exception ex) { _logger.Error(ex, "Failed to delete folder locally after 404."); } return true; } // --- Individual mail actions --- if (uiRequest is IMailActionRequest mailAction && error.Account != null) { _logger.Warning("Entity not found (404) for mail operation {Op} on {MailId}. Deleting locally.", mailAction.Operation, mailAction.Item.Id); // Revert optimistic UI change (e.g. mark-read/flag toggle) before deleting error.RequestBundle.UIChangeRequest?.RevertUIChanges(); try { await _mailService.DeleteMailAsync( error.Account.Id, mailAction.Item.Id).ConfigureAwait(false); } catch (Exception ex) { _logger.Error(ex, "Failed to delete mail locally after 404."); } return true; } // --- Batch requests (can't identify specific item) --- // Mark as recoverable. Next sync will clean up stale items. _logger.Warning("Entity not found (404) for batch operation. Marking as recoverable."); return true; } }