using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Entities.Store.ValueObject;
using Microsoft.EntityFrameworkCore;
using SharedKernel.Helpers;
using SharedKernel.Results;
namespace Application.Features.Admin.Store.Coupon.ExportCodes;
///
/// CSV 양식 (DB 컬럼명 기준):
/// ID, Code, Status, IssuedToMemberID, IssuedToMemberName, IssuedToMemberEmail, IssuedAt, UsedAt, CreatedAt
///
/// Status 인코딩 (사용자 결정 — Option A):
/// 0 = Available (미배포)
/// 1 = Reserved/Issued/Used (배포된 상태로 묶음)
///
/// 일시는 KST 로 출력 (UTC → Local 변환).
///
public sealed class Handler(IAppDbContext db) : IQueryHandler>
{
private static readonly string[] Header =
[
"ID",
"Code",
"Status",
"IssuedToMemberID",
"IssuedToMemberName",
"IssuedToMemberEmail",
"IssuedAt",
"UsedAt",
"CreatedAt"
];
public async Task> Handle(Query request, CancellationToken ct)
{
var coupon = await db.Coupon.AsNoTracking()
.Where(c => c.ID == request.CouponID)
.Select(c => new { c.ID, c.Name })
.FirstOrDefaultAsync(ct);
if (coupon is null)
{
return Result.Failure(Error.NotFound("Coupon.NotFound", "쿠폰을 찾을 수 없습니다."));
}
var rows = await db.CouponCode.AsNoTracking()
.Include(c => c.IssuedToMember)
.Where(c => c.CouponID == request.CouponID)
.OrderBy(c => c.ID)
.Select(c => new
{
c.ID,
c.Code,
c.Status,
c.IssuedToMemberID,
Name = c.IssuedToMember != null ? c.IssuedToMember.Name : null,
Email = c.IssuedToMember != null ? c.IssuedToMember.Email : null,
c.IssuedAt,
c.UsedAt,
c.CreatedAt
})
.ToListAsync(ct);
var csvRows = new List { Header };
foreach (var r in rows)
{
var status = r.Status == CouponCodeStatus.Available ? "0" : "1";
var memberID = r.IssuedToMemberID?.ToString() ?? "";
var name = r.Name ?? "";
var email = r.Email ?? "";
var issuedAt = r.IssuedAt.HasValue
? DateTime.SpecifyKind(r.IssuedAt.Value, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
: "";
var usedAt = r.UsedAt.HasValue
? DateTime.SpecifyKind(r.UsedAt.Value, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
: "";
var createdAt = DateTime.SpecifyKind(r.CreatedAt, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
csvRows.Add([
r.ID.ToString(),
r.Code,
status,
memberID,
name,
email,
issuedAt,
usedAt,
createdAt
]);
}
var bytes = CsvHelper.WriteUtf8Bom(csvRows);
var fileName = $"coupon-codes-{request.CouponID}-{DateTime.Now:yyyyMMdd-HHmmss}.csv";
return Result.Success(new Response(bytes, fileName));
}
}