package com.seatel.mobilehall.ui.home.activity

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import com.android.volley.NoConnectionError
import com.android.volley.Request
import com.android.volley.TimeoutError
import com.android.volley.VolleyError
import com.google.gson.Gson
import com.seatel.mobilehall.BuildConfig
import com.seatel.mobilehall.R
import com.seatel.mobilehall.data.network.SeatelJSONObjectRequest
import com.seatel.mobilehall.data.network.SeatelSuperRequest
import com.seatel.mobilehall.databinding.ActivityPaymentBinding
import com.seatel.mobilehall.ui.base.activity.BaseActivity
import com.seatel.mobilehall.ui.home.adapter.PaymentsAdapter
import com.seatel.mobilehall.ui.home.interactor.PaymentMethodListInteractor
import com.seatel.mobilehall.ui.home.interactor.ProfileInteractor
import com.seatel.mobilehall.ui.home.interactor.TopupTransactionInteractor
import com.seatel.mobilehall.ui.home.model.AbaFormModel
import com.seatel.mobilehall.ui.home.model.PaymentMethodModel
import com.seatel.mobilehall.ui.home.presenter.PaymentMethodListPresenter
import com.seatel.mobilehall.ui.home.presenter.ProfilePresenter
import com.seatel.mobilehall.ui.home.presenter.TopupTransactionPresenter
import com.seatel.mobilehall.ui.login.model.ProfileModel
import com.seatel.mobilehall.util.Constant
import com.seatel.mobilehall.util.SeatelAlertDialog
import com.seatel.mobilehall.util.SeatelUtils
import com.seatel.mobilehall.util.customview.ErrorHandleView
import org.json.JSONObject
import java.util.Locale

class PaymentActivity : BaseActivity<ActivityPaymentBinding>(), TopupTransactionInteractor.View,
    ProfileInteractor.View,
    PaymentMethodListInteractor.View {

    private var mPhoneNumber: String = ""
    private var mAmountTopup: Double = 0.0
    private var originalAmount: Double = 0.0
    private var mPinTopup: String = ""
    private var mTypePin: String = "pinless"
    private var mTopupStatus: String = ""
    private var mPaymentType: String = ""
    private var mAdapterPayActivity: PaymentsAdapter? = null
    private var mPaymentMethodListPresenter: PaymentMethodListPresenter? = null
    private var tran_id: String = ""
    private var return_params: String = ""
    private var checkCallBack = false
    private var TAG = PaymentActivity::class.java.simpleName
    private var isWingInstalled = 0
    private val WING_SCHEME_DEV = "com.wingmoney.wingpay.uat"
    private val WING_SCHEME_PRO = "com.wingmoney.wingpay"

    //Topup
    private lateinit var mTopupTransactionPresenter: TopupTransactionPresenter

    //Union Pay
    //   private lateinit var mUnionPayTransactionPresenter: UnionPayTransactionPresenter
    private var transactionNumber: String = ""
    private var orderId: String = ""
    private var handlerRefresh: Handler? = null
    private var mGridLayoutManager: GridLayoutManager? = null

    // “00” – UnionPay’s formal environment
    // “01” – UnionPay’s testing environment, where no real transaction occurs
    private val serverMode = "01"


    override fun onLoadDataSucceed(profileModel: ProfileModel) {
        binding.ctvUserName.text = profileModel.custName
    }

    override fun onLoadDataFailed(error: VolleyError) {
    }

    private fun abaPayway(amount: Double, remark: String, option: String) {
        object : SeatelJSONObjectRequest(this) {
            override fun getFunctionName(): String {
                return "aba/form?amount=$amount&remark=$remark|top-up&option=$option"
            }

            override fun getMethod(): Int {
                return Request.Method.GET
            }


        }.setOnErrorListener {
            SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(it)).show()
        }.execute {
            val response = it as JSONObject
            val link = response.optString("link")
            if (link.isNotBlank()) {
                AliPayPaymentActivity.lunch(
                    this, link, mAmountTopup, "Credit/Debit Card"
                )
            } else {
                val gson = Gson().fromJson(response.toString(), AbaFormModel::class.java)
                tran_id = gson.status.tran_id
                return_params = remark
                openDeepLink(gson.abapay_deeplink)
            }


        }

    }

    private fun isAppInstalled(packageName: String, context: Context): Boolean {
        val packageManager = context.packageManager
        return try {
            packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
            true
        } catch (e: PackageManager.NameNotFoundException) {
            false
        }
    }


    private fun openDeepLink(qrString: String) {
        checkCallBack = true
        try {
            val url = qrString/* val url =
                 "${ABA_SCHEME}://${ABA_DOMAIN}?type=payway&qrcode=${qrString}"*/ // value from "abapay_deeplink"
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
            startActivity(intent)
        } catch (ex: Exception) {
            gotoPlayStore()/*val intented: Intent = Intent(Intent.ACTION_VIEW).apply {
                //  intent.data = Uri.parse("market://details?id=com.paygo24.ibank")
                intent.data =
                    Uri.parse("https://play.google.com/store/apps/details?id=com.paygo24.ibank")
            }
            startActivity(intent)*/
        }
    }

    private fun gotoPlayStore() {
        try {
            startActivity(
                Intent(
                    Intent.ACTION_VIEW, Uri.parse("market://details?id=com.paygo24.ibank")
                )
            )
        } catch (obj: android.content.ActivityNotFoundException) {
            startActivity(
                Intent(
                    Intent.ACTION_VIEW,
                    Uri.parse("https://play.google.com/store/apps/details?id=com.paygo24.ibank")
                )
            )
        }

    }

    override fun onTopupSucceed(paymentType: String, remark: String, amount: Double) {
        mAmountTopup = amount
        if (TextUtils.equals(paymentType.lowercase(Locale.getDefault()), "wing")) {
            checkCallBack = false

            val isInstalled = isAppInstalled(WING_SCHEME_PRO, applicationContext)
            isWingInstalled = if (isInstalled) {
                // Application is installed
                1
            } else {
                0
                // Application is not installed
            }
            WingPaymentActivity.lunch(
                this,
                "${Constant.URL_WING_PAYMENT}amount=$mAmountTopup&remark=$remark&isWingAppInstalled=$isWingInstalled",
                mAmountTopup,
                isAbleBackPress = false,
                ShowValentineDayPromotion = false,
                phoneNumber = mPhoneNumber
            )
        } else if (TextUtils.equals(paymentType.lowercase(Locale.getDefault()), "aba")) {
            abaPayway(amount = mAmountTopup, remark = remark, option = "abapay_deeplink")
            // AbaActivity.lunch(this, mAmountTopup, remark)
            /*AliPayMpayPaymentActivity.lunch(
                this,
                "${Constant.URL_ABA_PAYMENT}amount=$mAmountTopup&remark=$remark",
                mAmountTopup,
                "ABA payway",
                true,
                true
            )*/
        } else if (TextUtils.equals(paymentType.lowercase(Locale.getDefault()), "aba-card")) {
            abaPayway(mAmountTopup, remark, "cards")
        } else if (TextUtils.equals(
                paymentType.lowercase(Locale.getDefault()), "mpay"
            ) or TextUtils.equals(
                paymentType.lowercase(Locale.getDefault()), "alipay"
            )
        ) {
            checkCallBack = false
            AliPayPaymentActivity.lunch(
                this,
                "${BuildConfig.BASE_URL}${paymentType.lowercase(Locale.getDefault())}/form?amount=$mAmountTopup&remark=$remark",
                mAmountTopup,
                paymentType
            )
        } else {
            if (TextUtils.equals(mTopupStatus.lowercase(Locale.getDefault()), "success")) {
                checkCallBack = false
                TopUpSuccessActivity.lunch(
                    this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
                )
            }

        }
    }

    override fun onTopupFailed(error: VolleyError) {
        showHideLoading(false)
        SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(error)).show()
        mPaymentType = ""

//        if (mAdapterPayActivity != null)
//            mAdapterPayActivity.resetSelectAll()
    }

    /* override fun onGetTransactionNumberSucceed(response: JSONObject) {
         if (response != null) {
             this.transactionNumber = response.optString("transactionNumber")
             this.orderId = response.optString("orderId")
       //      startUnionPayTransaction()
         }
     }
 *//* override fun onGetTransactionNumberFailed(error: VolleyError) {
         showHideLoading(false)
         SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(error)).show()
     }*/

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        showHideLoading(false)
        if (data == null) {
            return
        }
        if (requestCode == 10 && data.hasExtra("pay_result")) {
            val str = data.getStringExtra("pay_result")
            Log.d("onActivityResult", " $requestCode  $resultCode $str ")
            when {
                TextUtils.equals(str!!.lowercase(Locale.getDefault()), "success") -> {
                    mTopupStatus = "success"
                }

                TextUtils.equals(str.lowercase(Locale.getDefault()), "fail") -> {
                    mTopupStatus = "fail"
                }

                TextUtils.equals(str.lowercase(Locale.getDefault()), "cancel") -> {
                    mTopupStatus = "cancel"
                }
            }
            startTopupTransaction()
        } else if (requestCode == Constant.REQUEST_WING) {
            TopUpSuccessActivity.lunch(
                this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber.toString()
            )
        }
    }

    private fun startUnionPayProcess() {
        showHideLoading(true)
        //    mUnionPayTransactionPresenter.onGetTransactionNumber(mPhoneNumber.trim(), mAmountTopup)
    }


    private fun checkTopupPaymentTypeProcess(index: Int) {
        if (handlerRefresh == null) handlerRefresh = Handler()
        if (handlerRefresh != null) handlerRefresh?.postDelayed({
            mAdapterPayActivity?.notifyItemChanged(index)
            handlerRefresh?.removeCallbacksAndMessages(this)
            handlerRefresh = null
        }, 100)

        when (mPaymentType) {/*  "unionpay" -> {
                  startUnionPayProcess()
                  FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.UNION_PAY)
              }*/
            Constant.WING -> {
                startPaymentProcess("wing")
                //  FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.PAY_WING)
            }

            Constant.M_PAY -> {
                startPaymentProcess("mpay")
                // FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.M_PAY)
            }

            Constant.ALI_PAY -> {
                startPaymentProcess("alipay")
                //  FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.ALI_PAY)
            }

            Constant.ABA -> {
                startPaymentProcess("aba")
                // FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.ABA_PAY)
            }

            Constant.ABA_CARD -> {
                startPaymentProcess("aba-card")
            }

            else -> {
                SeatelAlertDialog.with(this, getString(R.string.choose_payment_option)).show()
                //  FirebaseAnalyticsUtil.getInstance(this).logCustomEvent(Constant.SeaTelAnalytics.Value.PAY_WING)
            }
        }

    }

    private fun startPaymentProcess(typePay: String) {
        showHideLoading(true)
        mTopupTransactionPresenter.onTopup(
            mPhoneNumber, "", "", "pinless", "", typePay, originalAmount
        )
    }

    fun showPaymentDetail(str: String, index: Int) {
        mPaymentType = str.lowercase(Locale.getDefault())
        checkTopupPaymentTypeProcess(index)
    }

    fun initUnionPay(str: String) {
        mPaymentType = str.lowercase(Locale.getDefault())
        checkTopupPaymentTypeProcess(0)
    }

    private fun showHideLoading(isShow: Boolean) {
        if (isShow) binding.errorView.setViewMode(ErrorHandleView.Mode.LOADING)
        else binding.errorView.visibility = View.GONE
    }

    private fun startUnionPayTransaction() {
        //  UPPayAssistEx.startPay(this, null, null, transactionNumber, serverMode)
    }

    private fun startTopupTransaction() {
        showHideLoading(true)
        mTopupTransactionPresenter.onTopup(
            mPhoneNumber, mPinTopup, orderId, mTypePin, mTopupStatus, mPaymentType, originalAmount
        )
    }

    override fun onGetPaymentMethodSucceed(paymentList: ArrayList<PaymentMethodModel>) {
        if (paymentList.size == 0) SeatelAlertDialog.with(this, getString(R.string.alert_payment))
            .show()
        showHideLoading(false)
        mAdapterPayActivity?.setDataMethod(paymentList)
        binding.recyclerViewPayment.adapter = mAdapterPayActivity
//        mGridLayoutManager = GridLayoutManager(this, 2)
//        binding.recyclerViewPayment.layoutManager = mGridLayoutManager
    }

    private fun updateLayoutRecyclerViewForAppGuide(isDone: Boolean = false) {
        val layout = binding.recyclerViewPayment.layoutParams
        if (isDone) layout.height = ViewGroup.LayoutParams.MATCH_PARENT
        else layout.height = ViewGroup.LayoutParams.WRAP_CONTENT
        binding.recyclerViewPayment.layoutParams = layout
    }


    override fun onGetPaymentMethodFailed(error: VolleyError) {
        when (error) {
            is TimeoutError -> {
                binding.errorView.errorMessage = getString(R.string.connection_timeout)
                binding.errorView.setViewMode(ErrorHandleView.Mode.TIME_OUT)
            }

            is NoConnectionError -> {
                binding.errorView.errorMessage = getString(R.string.message_no_internet)
                binding.errorView.setViewMode(ErrorHandleView.Mode.NO_INTERNET)
            }

            else -> SeatelAlertDialog.with(this, getString(R.string.alert_payment)).show()
        }
    }

    override fun getViewBinding(): ActivityPaymentBinding {
        return ActivityPaymentBinding.inflate(layoutInflater)
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        super.activityEnterRightAnimation()
      //  setContentView(R.layout.activity_payment)
        checkCallBack = false

        showHideLoading(true)
        mAdapterPayActivity = PaymentsAdapter(this)
        mPaymentMethodListPresenter = PaymentMethodListPresenter(this)
        mPaymentMethodListPresenter?.onGetPaymentMethod()

        mPhoneNumber = intent.getStringExtra(Constant.PHONE_NUMBER).toString()
        originalAmount = intent.getDoubleExtra(Constant.MPAY_AMOUNT, 0.0)

        binding.ctvPhoneNumberHeader.text = mPhoneNumber
        mPhoneNumber = mPhoneNumber.replace(" ", "")

        ProfilePresenter(this).loadData(mPhoneNumber)

        //    mUnionPayTransactionPresenter = UnionPayTransactionPresenter(this)
        mTopupTransactionPresenter = TopupTransactionPresenter(this, this)

        binding.tvAmount.text = "${binding.tvAmount.text}:"

        binding.ctvValuePrice.text = SeatelUtils.displayAmountNoDecial(this, "$$originalAmount")


    }

    private fun getAbaCallBack() {
        object : SeatelJSONObjectRequest(this) {
            override fun getFunctionName(): String {
                return "aba/callback"
            }

            override fun onGetBodyRequest(): String {

                val obj = JSONObject()
                obj.put("tran_id", tran_id)
                obj.put("status", "0")
                obj.put("return_params", return_params)

                return obj.toString()
            }

            override fun getMethod(): Int {
                return Request.Method.POST
            }

        }.setOnErrorListener {
            SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(it)).show()
        }.execute {
            val message = (it as JSONObject).optString("message")
            val status = it.optString("status")
            if (status.equals("pending")) {
                SeatelAlertDialog.with(this, message).show()
            }
            if (status.equals("ok")) {
                TopUpSuccessActivity.lunch(
                    this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
                )
            }
        }
    }

    override fun onBackPressed() {
        super.onBackPressed()
        super.activityExitLeftAnimation()
    }

    override fun getToolbarTitle(): String {
        return resources.getString(R.string.payments)
    }


    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume: ")
        mAdapterPayActivity?.notifyDataSetChanged()
        showHideLoading(false)
        if (checkCallBack) getAbaCallBack()
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val appLinkAction: String? = intent.action
        val appLinkData: Uri? = intent.data
        Log.d(TAG, "onNewIntent: ${appLinkData.toString()} $appLinkAction")

        if (appLinkData.toString().contains("transaction_status=true")) {
            TopUpSuccessActivity.lunch(
                this, Constant.TOPUP_SUCCESS, originalAmount.toString(), mPhoneNumber
            )
            finish()
        }


    }

    companion object {
        const val ABA_SCHEME = "abamobilebank"
        const val ABA_DOMAIN = "ababank.com"

        fun lunch(context: Context, phoneNumber: String, amountTopup: Double) {
            val intent = Intent(context, PaymentActivity::class.java)
            intent.putExtra(Constant.PHONE_NUMBER, phoneNumber)
            intent.putExtra(Constant.MPAY_AMOUNT, amountTopup)
            context.startActivity(intent)
        }
    }
}
