package com.pairplay.pairplay.presentation.payment import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.viewModels import com.pairplay.pairplay.BuildConfig import com.pairplay.pairplay.R import com.pairplay.pairplay.base.BaseActivityWithViewModel import com.pairplay.pairplay.binding.enabled import com.pairplay.pairplay.binding.onDebounceClick import com.pairplay.pairplay.databinding.ActivityPaymentBinding import com.pairplay.pairplay.domain.model.payment.GoodsOption import com.pairplay.pairplay.domain.model.payment.GoodsOptionId import com.pairplay.pairplay.extension.showToast import com.pairplay.pairplay.manager.EventBusManager import com.pairplay.pairplay.presentation.common.error import com.pairplay.pairplay.presentation.common.isLoading import com.pairplay.pairplay.presentation.common.success import com.tosspayments.paymentsdk.PaymentWidget import com.tosspayments.paymentsdk.model.AgreementStatus import com.tosspayments.paymentsdk.model.AgreementStatusListener import com.tosspayments.paymentsdk.model.PaymentCallback import com.tosspayments.paymentsdk.model.TossPaymentResult import com.tosspayments.paymentsdk.view.PaymentMethod import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @AndroidEntryPoint class PaymentActivity : BaseActivityWithViewModel() { private var isPaymentRendered = false companion object { fun createClubIntent( context: Context, productId: Long, productType: String, productPrice: Int, amount: Int, selectedSeats: List = listOf(), volt: Int, promotionCode: String = "", pairPlayCare: Boolean = false, purchaseCount: Int ) = createIntent( context, productId, productType, productPrice, amount, arrayListOf().apply { selectedSeats.forEach { add(GoodsOption(GoodsOptionId.SEAT.name, it)) } pairPlayCare.takeIf { it }?.let { add(GoodsOption(GoodsOptionId.CARE.name, true.toString())) } }, volt, promotionCode, purchaseCount ) fun createIntent( context: Context, productId: Long, productType: String, productPrice: Int, amount: Int, options: ArrayList = arrayListOf(), volt: Int, promotionCode: String = "", purchaseCount: Int ) = Intent(context, PaymentActivity::class.java).apply { putExtra(PaymentViewModel.KEY_PRODUCT_ID, productId.toString()) putExtra(PaymentViewModel.KEY_PRODUCT_TYPE, productType) putExtra(PaymentViewModel.KEY_PRODUCT_PRICE, productPrice) putExtra(PaymentViewModel.KEY_VOLT, volt) putExtra(PaymentViewModel.KEY_AMOUNT, amount) putParcelableArrayListExtra(PaymentViewModel.KEY_OPTIONS, options) putExtra(PaymentViewModel.KEY_PROMOTION_CODE, promotionCode) putExtra(PaymentViewModel.KEY_PURCHASE_COUNT, purchaseCount) } } override val viewModel: PaymentViewModel by viewModels() private lateinit var paymentWidget: PaymentWidget override fun layoutId(): Int = R.layout.activity_payment override fun onBindingCreated(binding: ActivityPaymentBinding) { paymentWidget = PaymentWidget( this@PaymentActivity, BuildConfig.PAYMENT_KEY, viewModel.email ) binding.viewModel = viewModel binding.buttonPayment.onDebounceClick(2000) { requestPayment() } } override fun bindViewModel(viewModel: PaymentViewModel) { viewModel.apply { order.launchInCreated { it.success { renderPayment() } } result.launchInCreated { it.success { setResult(RESULT_OK) // TODO : PAYMENT VOLT로만 결제한 경우 Status 변경 EventBusManager.notifyPaymentSuccess(paymentKey = "", orderId = "", amount = -1, delay = 1000) finish() }.error { errorCode, errorMessage, errorMessageRes -> setResult(RESULT_OK, Intent().apply { putExtra("errorCode", errorCode) putExtra("errorMessage", errorMessage) }) finish() } } initData(intent.extras) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel.loadOrder() } private fun renderPayment() { try { paymentWidget.apply { renderPaymentMethods(binding.paymentWidget, viewModel.amount) renderAgreement(binding.agreementWidget) addAgreementStatusListener(object : AgreementStatusListener { override fun onAgreementStatusChanged(agreementStatus: AgreementStatus) { isPaymentRendered = true // 실제 렌더링이 완료된 시점에 플래그 설정 binding.buttonPayment.enabled(agreementStatus.agreedRequiredTerms) } }) } } catch (e: Exception) { isPaymentRendered = false showToast("결제 위젯을 불러오는데 실패했습니다. 다시 시도해주세요.") } } private fun requestPayment() { binding.buttonPayment.isEnabled = false if (!isPaymentRendered) { showToast("아직 결제준비가 되지 않습니다. 잠시후 다시 시도해주세요.") binding.buttonPayment.isEnabled = true return } viewModel.order.value.success { if (viewModel.result.value.isLoading()) { binding.buttonPayment.isEnabled = true return@success } if (it.orderId != null && it.orderName != null) { viewModel.resultLoading(true) val paymentInfo = PaymentMethod.PaymentInfo(it.orderId, it.orderName).apply { customerName = it.userName customerEmail = viewModel.email } paymentWidget.requestPayment( paymentInfo, object : PaymentCallback { override fun onPaymentFailed(fail: TossPaymentResult.Fail) { Timber.d("renderPayment onPaymentFailed() : ${fail.errorCode} ${fail.errorMessage}") showToast(fail.errorMessage) viewModel.resultLoading(false) binding.buttonPayment.isEnabled = true } override fun onPaymentSuccess(success: TossPaymentResult.Success) { viewModel.requestApproval(success.paymentKey, success.orderId) binding.buttonPayment.isEnabled = true } } ) } } } }