using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using GB5Shared.DTO.ECM;
using GB5Shared.FileUpload;
using GB5Shared.DTO.Framework.Login;
using static GB5Shared.GB5Constant.Constant;
using EntityConst = GB5Shared.GB5Constant.Constant.EntityConstant;
namespace FrameworkBLL.SystemJob
{
///
/// Internal executor utility — called by SysJobExecutorQuartzJob when it detects
/// that a report service returned a binary file response (application/pdf, xlsx, csv, etc.).
///
/// Report services have no knowledge of DMS or this helper. They simply return the file
/// as a standard HTTP response:
/// HTTP 200 OK
/// Content-Type: application/pdf
/// Content-Disposition: attachment; filename="SalesReport_July2026.pdf"
/// [binary body]
///
/// The executor detects the binary content-type, calls UploadAsync here to store the
/// file in TATTACHMENT linked to the TSYSJOB row, and writes "att:{attachmentId}" to
/// TSYSJOB.RESULTLOCATION. GetSystemJobResult reads that token and streams the file
/// back from DMS to the client.
///
public static class SysJobAttachmentHelper
{
///
/// Uploads a report file to DMS linked to the given SysJob and returns "att:{attachmentId}".
///
/// Injected IFileUploadBLL from the calling BLL.
/// Complete file content (PDF, Excel, CSV, etc.).
/// User-visible filename, e.g. "SalesReport_2026.pdf".
/// MIME type, e.g. "application/pdf".
/// The TSYSJOB.SYSJOBID this file belongs to.
/// Caller's login — determines tenant and uploader identity.
/// Cancellation token.
/// "att:{attachmentId}" — store this in TSYSJOB.RESULTLOCATION.
public static async Task UploadAsync(
IFileUploadBLL fileUploadBLL,
byte[] fileBytes,
string displayFileName,
string mimeType,
int sysJobId,
LoginDTO login,
CancellationToken ct = default)
{
if (fileBytes is null || fileBytes.Length == 0)
throw new ArgumentException("File content must not be empty.", nameof(fileBytes));
if (string.IsNullOrWhiteSpace(displayFileName))
throw new ArgumentException("Display file name must not be empty.", nameof(displayFileName));
string base64 = Convert.ToBase64String(fileBytes);
var request = new FileUploadBase64RequestDTO
{
FileName = displayFileName,
DisplayFileName = displayFileName,
Base64Content = base64,
ObjectId = sysJobId,
ObjectTypeId = EntityConst.OBJECTSYSTEMJOB, // -1399960001
DocumentDetailId = -1,
BizTransactionTypeId = -1,
AttachmentType = 0, // File (not link)
DocumentTypeId = -1,
ClassificationMarkId = -1,
SlNo = 1,
Status = 1,
Remarks = $"Report output for SysJob {sysJobId}",
};
var result = await fileUploadBLL.FileUploadBase64Async(request, login).ConfigureAwait(false);
return $"att:{result.AttachmentId}";
}
///
/// Overload accepting a Stream instead of a byte array — avoids double-buffering for
/// callers that already have the file as a stream (e.g. MemoryStream from QuestPDF/ClosedXML).
/// The stream is read to completion; the caller is responsible for disposing it.
///
public static async Task UploadAsync(
IFileUploadBLL fileUploadBLL,
Stream fileStream,
string displayFileName,
string mimeType,
int sysJobId,
LoginDTO login,
CancellationToken ct = default)
{
using var ms = new MemoryStream();
await fileStream.CopyToAsync(ms, ct).ConfigureAwait(false);
return await UploadAsync(fileUploadBLL, ms.ToArray(), displayFileName, mimeType, sysJobId, login, ct)
.ConfigureAwait(false);
}
}
}