using FastEndpoints; using FrameworkBLL.DataSync; using FrameworkDAL.DTO.DataSync; using GB5Shared.DTO.Framework.Login; using GB5Shared.FastEndPoint; using Microsoft.AspNetCore.Http; using static GB5Shared.GB5Constant.Constant; namespace FrameworkSL.Endpoints.DataSync { // Returns a ZIP file stream. BaseEndpoint is not used here because the // response is a raw blob stream rather than ResponseStandardDTO — handled via // HttpContext.Response directly. public class ExportToFile : EndpointWithoutRequest { private readonly IDataSyncExportBLL _bll; public ExportToFile(IDataSyncExportBLL bll) => _bll = bll; public override void Configure() { Get("/DataSync/ExportToFile"); AllowAnonymous(); } public override async Task HandleAsync(CancellationToken ct) { var loginHeader = HttpContext.Request.Headers["Login"].FirstOrDefault() ?? throw new InvalidOperationException("Login header is missing."); var login = System.Text.Json.JsonSerializer.Deserialize(loginHeader) ?? throw new InvalidOperationException("Login header contains invalid JSON."); int.TryParse(Query("SyncJobId"), out var syncJobId); var exportMode = Query("ExportMode") ?? "Incremental"; DateTime? fromDate = null; DateTime? toDate = null; if (Query("FromDate") is { } fd && DateTime.TryParse(fd, out var fdt)) fromDate = fdt; if (Query("ToDate") is { } td && DateTime.TryParse(td, out var tdt)) toDate = tdt; var req = new SyncExportRequestDTO { SyncJobId = syncJobId, ExportMode = exportMode, FromDate = fromDate, ToDate = toDate }; try { await using var stream = await _bll.ExportToZipAsync(req, login, ct).ConfigureAwait(false); var ts = DateTime.UtcNow.ToString("yyyyMMdd-HHmm"); var fileName = $"datasync-export-{syncJobId}-{ts}.zip"; HttpContext.Response.ContentType = "application/zip"; HttpContext.Response.Headers["Content-Disposition"] = $"attachment; filename=\"{fileName}\""; await stream.CopyToAsync(HttpContext.Response.Body, ct).ConfigureAwait(false); } catch (Exception ex) { HttpContext.Response.StatusCode = 500; await HttpContext.Response.WriteAsync(ex.Message, ct).ConfigureAwait(false); } } } }