using GB5Shared.DTO.ECM; using GB5Shared.DTO.Framework.Login; using GB5Shared.FileImport; using GB5Shared.FileUpload; using GB5Shared.QueueReader; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using PayRollBLL.Employee; using PayRollDAL.DTO.EmployeeAttachmentImport; using System; using System.Data; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using static GB5Shared.GB5Constant.Constant; namespace PayRollBLL.EmployeeAttachmentImport { // GB4 parity: EmployeeToUserBulkImportAsynchImport's worker (EmployeeToUserCsvAsynch) — // reads the manifest, does the per-row work, writes an import log. // Manifest columns expected: EMPLOYEECODE, FILENAME. public class EmployeeAttachmentBulkImportJobHandler : IJobQueueHandler { public string MessageType => EmployeeAttachmentImportBLL.MessageType; private readonly IFileToDataTableService _fileToDataTableService; private readonly IFileUploadBLL _fileUploadBLL; private readonly IEmployeeBLL _employeeBLL; private readonly IConfiguration _configuration; public EmployeeAttachmentBulkImportJobHandler( IFileToDataTableService fileToDataTableService, IFileUploadBLL fileUploadBLL, IEmployeeBLL employeeBLL, IConfiguration configuration) { _fileToDataTableService = fileToDataTableService; _fileUploadBLL = fileUploadBLL; _employeeBLL = employeeBLL; _configuration = configuration; } public async Task HandleAsync(string payload, LoginDTO login, long queueId, CancellationToken ct) { var jobDTO = JsonConvert.DeserializeObject(payload) ?? throw new InvalidOperationException("Invalid EmployeeAttachmentBulkImportJobDTO payload."); string manifestPath = EmployeeAttachmentImportBLL.GetManifestPath(_configuration, jobDTO.FileName); string attachmentFolder = Path.GetDirectoryName(manifestPath)!; ImportFileTypeEnum fileType = Path.GetExtension(manifestPath).TrimStart('.').ToLowerInvariant() == "csv" ? ImportFileTypeEnum.Csv : ImportFileTypeEnum.Excel; DataTable manifest = await _fileToDataTableService.ReadAsync(manifestPath, fileType, ct); var log = new StringBuilder(); int successCount = 0; int failureCount = 0; foreach (DataRow row in manifest.Rows) { string employeeCode = Convert.ToString(row["EMPLOYEECODE"]) ?? ""; string attachmentFileName = Convert.ToString(row["FILENAME"]) ?? ""; try { if (string.IsNullOrWhiteSpace(employeeCode) || string.IsNullOrWhiteSpace(attachmentFileName)) throw new InvalidOperationException("EMPLOYEECODE and FILENAME are required."); int employeeId = await _employeeBLL.GetEmployeeIdByCode(employeeCode, login); if (employeeId == -1) throw new InvalidOperationException($"No employee found for EmployeeCode '{employeeCode}'."); string attachmentFilePath = Path.Combine(attachmentFolder, attachmentFileName); if (!File.Exists(attachmentFilePath)) throw new InvalidOperationException($"Attachment file not found: {attachmentFilePath}"); byte[] fileBytes = await File.ReadAllBytesAsync(attachmentFilePath, ct); var uploadRequest = new FileUploadBase64RequestDTO { FileName = attachmentFileName, Base64Content = Convert.ToBase64String(fileBytes), ObjectId = employeeId, ObjectTypeId = EntityConstant.OBJECTEMPLOYEE }; await _fileUploadBLL.FileUploadBase64Async(uploadRequest, login); successCount++; log.AppendLine($"Record saved for {employeeCode} ({attachmentFileName})"); } catch (Exception ex) { if (jobDTO.IsSkip == 0) throw; failureCount++; log.AppendLine($"Record not saved for {employeeCode} ({attachmentFileName}) because of {ex.Message}"); } } string logPath = Path.Combine(attachmentFolder, $"{Path.GetFileNameWithoutExtension(jobDTO.FileName)}_IMPORT.txt"); await File.WriteAllTextAsync(logPath, $"Total: {manifest.Rows.Count}, Success: {successCount}, Failed: {failureCount}\r\n\r\n{log}", ct); } } }