private static void RenameAndArchive(ref string filePath, string prefix, string suffix, string extension, BulkActionUploadDto bulkActionUpload)
        {
            try
            {
                if (prefix.EndsWith(BulkActionConstants.Working, StringComparison.InvariantCultureIgnoreCase))
                {
                    var idx = prefix.LastIndexOf(BulkActionConstants.Working);
                    prefix = prefix.Substring(0, idx);
                }

                RenameFile(ref filePath, prefix, suffix, extension);
            }
            catch (Exception ex)
            {
                logger.BulkActionError($"Upload succeeded, but failed to rename file: {ex.Message}");
            }

            try
            {
                ArchiveFile(filePath, bulkActionUpload.FileArchiveDirectory, logger);
            }
            catch (Exception ex)
            {
                logger.BulkActionError($"Upload succeeded, but failed to archive file: {ex.Message}");
            }
        }
        public static void ProcessBulkAction(BulkActionUploadDto bulkActionUpload)
        {
            try
            {
                logger.BulkActionInfo("ProcessBulkAction enter");

                DocumentManager manager = new DocumentManager();

                // Check read/write permissions.
                if (!manager.ValidateDirectory(bulkActionUpload.FileUploadDirectory) ||
                    !manager.ValidateDirectory(bulkActionUpload.FileArchiveDirectory))
                {
                    NotificationService.ErrorNotification("Bulk Action", $"{bulkActionUpload.FileUploadDirectory} does not authorize read and write updates");
                    logger.BulkActionError($"{bulkActionUpload.FileUploadDirectory} does not authorize read and write updates");
                    throw new Exception($"{bulkActionUpload.FileUploadDirectory} does not authorize read and write updates");
                }


                logger.BulkActionInfo($"Loading files from \"{bulkActionUpload.FileUploadDirectory}\"");// Get all files to process.
                string[] filesToProcess =
                    Directory.GetFiles(bulkActionUpload.FileUploadDirectory)
                    .Select(fileName => Path.Combine(bulkActionUpload.FileUploadDirectory, fileName))
                    .ToArray();

                foreach (string f in filesToProcess)
                {
                    var filePath = f;
                    logger.BulkActionInfo($"Processing file \"{filePath}\"");

                    try
                    {
                        var directory = Path.GetDirectoryName(filePath);
                        var prefix    = Path.Combine(directory, Path.GetFileNameWithoutExtension(filePath));
                        var extension = Path.GetExtension(filePath);

                        //Note that while processing a file in the Upload directory, we rename it to provide for status
                        //indication and also to help handle situations where archiving fails, or when the server resets.

                        //1234.csv --> not yet processed.
                        //1234.working.csv --> currently being processed, but not yet uploaded to student forms.
                        //1234.complete.csv --> successfully uploaded to student forms
                        //1234.failed.csv --> rejected by student forms

                        if (prefix.EndsWith(BulkActionConstants.Working, StringComparison.InvariantCultureIgnoreCase))
                        {
                            //This can happen if the server reset before we had an opportunity to fully upload the file.
                            //Let's just reprocess.
                            logger.Info($"Encountered a working file.  Reprocessing: \"{filePath}\"");
                        }
                        else if (prefix.EndsWith(BulkActionConstants.Complete, StringComparison.InvariantCultureIgnoreCase) ||
                                 prefix.EndsWith(BulkActionConstants.Failed, StringComparison.InvariantCultureIgnoreCase))
                        {
                            try
                            {
                                logger.BulkActionInfo($"Encountered an already-processed file \"{filePath}\", attempting to archive");
                                ArchiveFile(filePath, bulkActionUpload.FileArchiveDirectory, logger);
                            }
                            catch (Exception ex)
                            {
                                logger.BulkActionError(ex);
                            }

                            //At this point, we're done processing the completed file - either with success or failure.  Let's
                            //continue on to the next file.
                            continue;
                        }
                        else
                        {
                            //We've encountered a file that's ready for processing.  We first rename it to .working to indicate that
                            //the file is currently being processed.
                            RenameFile(ref filePath, prefix, BulkActionConstants.Working, extension);
                        }

                        HttpResponseMessage result = Task.Run(() => manager.UploadBulkAction(bulkActionUpload, filePath)).Result;

                        logger.BulkActionInfo($"Bulk action upload completed with {result.StatusCode}");

                        if (result.IsSuccessStatusCode)
                        {
                            //Rename the file to .complete and then attempt to archive it.
                            RenameAndArchive(ref filePath, prefix, BulkActionConstants.Complete, extension, bulkActionUpload);
                        }
                        else
                        {
                            if (result.Content == null)
                            {
                                // Never hit the API...failed validation.
                                throw new Exception(result.ReasonPhrase);
                            }
                            else
                            {
                                // Build error message to send to notitification service
                                var importResult = Task.Run(() => result.Content.ReadAsAsync <ImportResult>()).Result;

                                //Rename the file to .failed and then attempt to archive it.
                                RenameAndArchive(ref filePath, prefix, BulkActionConstants.Failed, extension, bulkActionUpload);

                                throw new Exception(FormatImportResultMessage(importResult, filePath));
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.BulkActionError(ex);

                        try
                        {
                            logger.BulkActionInfo($"Attempting to send notification email to: \"{bulkActionUpload.NotificationEmail}\"");
                            // what to do if a file fails...
                            var response = Task.Run(() => notificationManager.SendErrorNotification("ProcessBulkAction", ex.Message, bulkActionUpload.NotificationEmail)).Result;

                            if (response.SendCompleted.HasValue)
                            {
                                logger.BulkActionInfo("Send notification email completed without error");
                            }
                            else
                            {
                                logger.BulkActionInfo("Send notification email failed");
                            }
                        }
                        catch (Exception ex2)
                        {
                            logger.BulkActionError($"Send notification email failed with error: \"{ex2.Message}\"");
                        }
                    }
                }
            }
            finally
            {
                logger.BulkActionInfo("ProcessBulkAction exit");
            }
        }