package roomescape.payment.web import roomescape.payment.exception.PaymentErrorCode import roomescape.payment.exception.PaymentException import roomescape.payment.infrastructure.common.PaymentStatus import roomescape.payment.infrastructure.common.PaymentType import roomescape.payment.infrastructure.persistence.* import roomescape.payment.web.PaymentDetailResponse.BankTransferDetailResponse import roomescape.payment.web.PaymentDetailResponse.CardDetailResponse import roomescape.payment.web.PaymentDetailResponse.EasyPayPrepaidDetailResponse import java.time.LocalDateTime import java.time.OffsetDateTime data class PaymentConfirmRequest( val paymentKey: String, val orderId: String, val amount: Int, val paymentType: PaymentType ) data class PaymentCreateResponse( val paymentId: Long, val detailId: Long ) data class PaymentCancelRequest( val reservationId: Long, val cancelReason: String, val requestedAt: LocalDateTime = LocalDateTime.now() ) data class PaymentRetrieveResponse( val orderId: String, val totalAmount: Int, val method: String, val status: PaymentStatus, val requestedAt: OffsetDateTime, val approvedAt: OffsetDateTime, val detail: PaymentDetailResponse, val cancel: PaymentCancelDetailResponse?, ) fun PaymentEntity.toRetrieveResponse( detail: PaymentDetailResponse, cancel: PaymentCancelDetailResponse? ): PaymentRetrieveResponse { return PaymentRetrieveResponse( orderId = this.orderId, totalAmount = this.totalAmount, method = this.method.koreanName, status = this.status, requestedAt = this.requestedAt, approvedAt = this.approvedAt, detail = detail, cancel = cancel ) } sealed class PaymentDetailResponse { data class CardDetailResponse( val type: String = "CARD", val issuerCode: String, val cardType: String, val ownerType: String, val cardNumber: String, val amount: Int, val approvalNumber: String, val installmentPlanMonths: Int, val easypayProviderName: String?, val easypayDiscountAmount: Int?, ) : PaymentDetailResponse() data class BankTransferDetailResponse( val type: String = "BANK_TRANSFER", val bankName: String, ) : PaymentDetailResponse() data class EasyPayPrepaidDetailResponse( val type: String = "EASYPAY_PREPAID", val providerName: String, val amount: Int, val discountAmount: Int, ) : PaymentDetailResponse() } fun PaymentDetailEntity.toPaymentDetailResponse(): PaymentDetailResponse { return when (this) { is PaymentCardDetailEntity -> this.toCardDetailResponse() is PaymentBankTransferDetailEntity -> this.toBankTransferDetailResponse() is PaymentEasypayPrepaidDetailEntity -> this.toEasyPayPrepaidDetailResponse() else -> throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE) } } fun PaymentCardDetailEntity.toCardDetailResponse(): CardDetailResponse { return CardDetailResponse( issuerCode = this.issuerCode.koreanName, cardType = this.cardType.koreanName, ownerType = this.ownerType.koreanName, cardNumber = this.cardNumber, amount = this.amount, approvalNumber = this.approvalNumber, installmentPlanMonths = this.installmentPlanMonths, easypayProviderName = this.easypayProviderCode?.koreanName, easypayDiscountAmount = this.easypayDiscountAmount ) } fun PaymentBankTransferDetailEntity.toBankTransferDetailResponse(): BankTransferDetailResponse { return BankTransferDetailResponse( bankName = this.bankCode.koreanName ) } fun PaymentEasypayPrepaidDetailEntity.toEasyPayPrepaidDetailResponse(): EasyPayPrepaidDetailResponse { return EasyPayPrepaidDetailResponse( providerName = this.easypayProviderCode.koreanName, amount = this.amount, discountAmount = this.discountAmount ) } data class PaymentCancelDetailResponse( val cancellationRequestedAt: LocalDateTime, val cancellationApprovedAt: OffsetDateTime?, val cancelReason: String, val canceledBy: Long, ) fun CanceledPaymentEntity.toCancelDetailResponse(): PaymentCancelDetailResponse { return PaymentCancelDetailResponse( cancellationRequestedAt = this.requestedAt, cancellationApprovedAt = this.canceledAt, cancelReason = this.cancelReason, canceledBy = this.canceledBy ) }