using System.Security.Cryptography; using System.Text; using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Api.V1.Coupons.GetCode; internal sealed class Handler(IAppDbContext db) : IQueryHandler> { public async Task> Handle(Query request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.Code)) { return Result.Failure(Error.Problem("Coupon.CodeRequired", "쿠폰 코드는 필수입니다.")); } var codeHash = ComputeHash(request.Code.Trim()); var row = await db.CouponCode .AsNoTracking() .Where(c => c.CodeHash == codeHash) .Select(c => new { c.Code, c.CouponID, CouponName = c.Coupon!.Name, c.Status, c.IssuedAt, c.UsedAt }) .FirstOrDefaultAsync(ct); if (row is null) { return Result.Failure(Error.NotFound("Coupon.CodeNotFound", "해당 쿠폰 코드를 찾을 수 없습니다.")); } var label = row.Status switch { CouponCodeStatus.Available => "미발급", CouponCodeStatus.Reserved => "결제 진행 중", CouponCodeStatus.Issued => "발급됨", CouponCodeStatus.Used => "사용 완료", CouponCodeStatus.Expired => "만료", _ => row.Status.ToString() }; return Result.Success(new Response( row.Code, row.CouponID, row.CouponName, (int)row.Status, label, row.IssuedAt, row.UsedAt )); } private static string ComputeHash(string code) { var bytes = Encoding.UTF8.GetBytes(code); var hash = SHA256.HashData(bytes); return Convert.ToHexString(hash); } }