package com.nhnkcp.mobilePaySample

import android.os.Bundle
import android.text.InputFilter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.RadioGroup
import androidx.core.view.children
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import com.nhnkcp.mobilePayLibrary.contants.PaymentCode
import com.nhnkcp.mobilePayLibrary.model.Payment
import com.nhnkcp.mobilePaySample.databinding.FragmentInputBinding

class InputFragment(
    private val code: String,
    private val completion: (Payment) -> Unit
) : Fragment() {
    private lateinit var binding: FragmentInputBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_input, container, false)
        initView()
        setListener()
        return binding.root
    }

    private fun setListener() {
        // 요청 인증번호 생성 버튼 클릭시 생성한 번호 표시
        binding.buttonCreate.setOnClickListener {
            binding.editVerificationCode.setText(getVerificationCode())
        }
        // 요청하기 버튼 클릭시 입력한 결제 데이터 전달
        binding.buttonRequest.setOnClickListener {
            completion.invoke(getPayment())
        }
    }

    private fun initView() {
        // 필수 입력 항목을 제외한 모든 레이아웃 보이지 않도록 지정
        val requiredList = listOf(R.id.layout_paydo_id, R.id.layout_business_no, R.id.layout_tid)
        binding.layoutInput.children.filter { it.id !in requiredList }
            .forEach { it.isVisible = false }
        // 요청 구분에 따라 화면 입력 항목 변경
        when (code) {
            PaymentCode.PAYMENT_CARD_APPROVAL,
            PaymentCode.PAYMENT_EASY_PAY_APPROVAL -> {
                binding.layoutPayment.isVisible = true
                binding.layoutPrint.isVisible = true
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_CARD_CANCEL,
            PaymentCode.PAYMENT_EASY_PAY_CANCEL -> {
                binding.layoutPayment.isVisible = true
                binding.layoutCancel.isVisible = true
                binding.layoutPrint.isVisible = true
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_CASH_APPROVAL -> {
                binding.layoutPayment.isVisible = true
                binding.layoutInstallment.isVisible = false
                binding.layoutCash.isVisible = true
                binding.layoutCancelCode.isVisible = false
                binding.layoutPrint.isVisible = true
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_CASH_CANCEL -> {
                binding.layoutPayment.isVisible = true
                binding.layoutInstallment.isVisible = false
                binding.layoutCash.isVisible = true
                binding.layoutCancel.isVisible = true
                binding.layoutPrint.isVisible = true
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_SIMPLE_RECEIPT -> {
                binding.layoutPayment.isVisible = true
                binding.layoutInstallment.isVisible = false
                binding.layoutPrint.isVisible = true
                binding.layoutOption.isVisible = false
            }
            PaymentCode.PAYMENT_PRINT_RECEIPT -> {
                binding.layoutCancel.isVisible = true
                binding.textTradeDate.text = "승인일자"
                val maxLength = InputFilter.LengthFilter(12)
                binding.editTradeDate.filters = arrayOf(maxLength)
                binding.layoutPrint.isVisible = true
                binding.layoutOption.isVisible = false
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_SEND_RECEIPT -> {
                binding.layoutCancel.isVisible = true
                binding.textTradeDate.text = "승인일자"
                val maxLength = InputFilter.LengthFilter(12)
                binding.editTradeDate.filters = arrayOf(maxLength)
                binding.layoutVerification.isVisible = true
            }
            PaymentCode.PAYMENT_RESULT -> {
                binding.layoutTradeNo.isVisible = true
                binding.layoutVerification.isVisible = true
            }
        }
    }

    private fun getPayment(): Payment {
        return Payment(
            // 결제프로그램 연동시, 동작을 구분하는 전문코드
            paymentCode = code,
            // 페이두 그룹아이디 5자리
            // 등록된 가맹점 그룹아이디와 일치하지 않으면 결제불가.
            groupId = getInputData(binding.editPaydoId),
            // 가맹점 사업자 번호 10자리
            // 등록된 가맹점 사업자번호와 일치하지 않으면 결제불가.
            businessNo = getInputData(binding.editBusinessNo),
            // 단말기 번호 Tid
            // 등록된 가맹점 단말기번호와 일치하지 않으면 결제불가.
            tid = getInputData(binding.editTid),
            // 결제프로그램에서 영수증을 출력할지 여부.
            isReceiptPrint = binding.checkboxRequiredPrint.isChecked,
            // 거래결과 화면 표시 여부
            // 해당값이 true일 경우, 거래결과 화면을 표시하지 않으며
            // 영수증 출력여부(isReceiptPrint)와 관계없이 영수증 출력 불가능.
            autoExit = binding.checkboxAutoExit.isChecked,
            // 결제할 총금액(판매금액 + 세금 + 봉사료)
            // 결제할 총금액이 50,000원 이하면 무서명 진행됩니다.
            totalAmount = getInputData(binding.editAmount)?.toInt(),
            // 할부개월 일시불일 경우 0(Max : 2 bytes)
            // 결제할 총 금액이 50,000원 이상인 경우 할부개월 입력이 가능함.
            // 필수참고사항! -> 50,000원 미만인 경우 무조건 일시불.
            installment = getInputData(binding.editInstallment)?.toInt(),
            // 부가세 등 세금(Max : 9 bytes)
            // 세금 0원 입력시 아래와 같은 세금계산방법으로 자동 진행됨.
            // 거래금액 = 결제할 총금액 - 봉사료
            // 세금 = (거래금액 * 10) / (100 + 10)
            tax = getInputData(binding.editTax)?.toInt(),
            // 면세 금액 등 비과세 항목(Max : 9 bytes)
            dutyFree = getInputData(binding.editDutyFree)?.toInt(),
            // 봉사료. 사용안할 시에는 0(Max : 9 bytes)
            tip = getInputData(binding.editTip)?.toInt(),
            // 현금영수증 발급용도(Max: 1 byte)
            // 소득공제 : 0, 지출증빙 : 1, 자진발급 : 2
            cashType = getSelectedIndex(binding.radioGroupCashType),
             // 현금영수증 취소사유(Max: 1 byte)
             // 거래취소 : 1, 오류발급: 2, 기타 : 3
            cancelCode = getSelectedIndex(binding.radioGroupCancelCode) + 1,
            // 현금영수증 발급번호
            // 핸드폰번호, 사업자등록번호 등이 가능함. (카드번호는 불가능)
            // 해당값이 없을 경우 결제프로그램에서 카드리딩,직접입력이 가능함.
            privacy = getInputData(binding.editPrivacy),
            // 추가인쇄내용(Max : 800 bytes)
            // 승인 전표에 별도로 인쇄되는 내용.(영수증 이미지는 적용안됨)
            // 프린터 인쇄폭은 32Byte,
            // 줄구분은 \n 2 bytes 사용, 줄당 최대 글자수 32 bytes
            // 원거래 승인시 통보받은 일자. 'yyMMddHHmmss' 형태의 문자열
            tradeDate = getInputData(binding.editTradeDate),
            // 원거래 승인시 통보받은 승인번호
            approvalNo = getInputData(binding.editApprovalNo),
            // 추가인쇄내용(Max : 800 bytes)
            // 승인 전표에 별도로 인쇄되는 내용.(영수증 이미지는 적용안됨)
            // 프린터 인쇄폭은 32Byte,
            // 줄구분은 \n 2 bytes 사용, 줄당 최대 글자수 32 bytes
            printData = getInputData(binding.editPrintData),
            // 요청인증번호(Max : 15 bytes)
            // 요청하는 거래건에 사용했던 요청인증번호 입력
            verificationCode = binding.editVerificationCode.text.toString()
        )
    }

    private fun getVerificationCode(): String? {
        /* 요청 인증번호는 App to App 을 이용해 결제할 경우 중복결제 방지 등을 위해 업무용 앱에서 요청 인증번호를 생성하고 페이두 앱으로 전달합니다.
        (업무용 앱과 페이두 앱에서만 사용되는 파라미터입니다.)
        요청 인증번호 파라미터는 최대 15 bytes 길이로 표현됩니다.
        신용결제(N01), 신용취소(N02), 현금결제(N03), 현금취소(N04)의 각 거래건마다
        유니크한 값을 업무용 App에서 생성하여 'setVerificationCode' 파라미터에 넣어 전달합니다.
        - 거래요청 후 getTradeResultCode(응답코드)가 '0000'(정상승인)인 경우에만
        업무용 App에서는 다음 거래에 사용될 거래번호를 다시 유니크한 값으로 생성하시기 바랍니다.
        - 거래요청 후 응답코드가 '0000'이 아닌 경우나 응답데이터를 못 받은 경우는
        정상승인 거래가 아니므로 기존에 요청했던 거래번호는 유지되어야만 중복결제 방지가 가능합니다.
        - 아래 코드는 예시입니다. 각 업체별 유니크한값 생성하여 사용 바랍니다.
        - 반드시 아래의 코드는 'MC'로 시작되어야 합니다.
        */
        return if (code == PaymentCode.PAYMENT_RESULT)
            getInputData(binding.editTradeNo)
        else "MC${System.currentTimeMillis()}"
    }

    private fun getInputData(editText: EditText) :String? {
        return editText.text.toString().ifBlank { null }
    }

    private fun getSelectedIndex(radioGroup: RadioGroup): Int =
        radioGroup.indexOfChild(binding.root.findViewById(radioGroup.checkedRadioButtonId))
}