package kr.co.vividnext.sodalive.mypage.can.charge.iap

import android.annotation.SuppressLint
import android.graphics.Rect
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ConsumeParams
import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.Purchase
import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.QueryProductDetailsParams
import com.android.billingclient.api.QueryPurchasesParams
import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.FragmentCanChargeIapBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity
import org.koin.android.ext.android.inject

class CanChargeIapFragment : BaseFragment<FragmentCanChargeIapBinding>(
    FragmentCanChargeIapBinding::inflate
) {
    private val viewModel: CanChargeIapViewModel by inject()

    private lateinit var adapter: CanChargeIapAdapter
    private lateinit var loadingDialog: LoadingDialog
    private lateinit var billingClient: BillingClient

    private val handler = Handler(Looper.getMainLooper())
    private var selectedProductDetails: ProductDetails? = null

    private lateinit var purchaseUpdateListener: PurchasesUpdatedListener

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        loadingDialog = LoadingDialog(requireActivity(), layoutInflater)

        bindData()
        setupRecyclerView()
        setupBillingClient()
    }

    override fun onDestroy() {
        billingClient.endConnection()
        super.onDestroy()
    }

    private fun bindData() {
        viewModel.isLoading.observe(viewLifecycleOwner) {
            if (it) {
                loadingDialog.show(screenWidth)
            } else {
                loadingDialog.dismiss()
            }
        }

        viewModel.toastLiveData.observe(viewLifecycleOwner) {
            Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show()
        }
    }

    private fun setupRecyclerView() {
        val recyclerView = binding.rvChargeCan
        adapter = CanChargeIapAdapter { productDetails ->
            selectedProductDetails = productDetails
            launchPurchaseFlow(productDetails)
        }

        recyclerView.layoutManager = LinearLayoutManager(
            requireContext(),
            LinearLayoutManager.VERTICAL,
            false
        )

        recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(
                outRect: Rect,
                view: View,
                parent: RecyclerView,
                state: RecyclerView.State
            ) {
                super.getItemOffsets(outRect, view, parent, state)

                outRect.left = 13.3f.dpToPx().toInt()
                outRect.right = 13.3f.dpToPx().toInt()

                when (parent.getChildAdapterPosition(view)) {
                    0 -> {
                        outRect.top = 13.3f.dpToPx().toInt()
                        outRect.bottom = 6.7f.dpToPx().toInt()
                    }

                    adapter.itemCount - 1 -> {
                        outRect.top = 6.7f.dpToPx().toInt()
                        outRect.bottom = 26.7f.dpToPx().toInt()
                    }

                    else -> {
                        outRect.top = 6.7f.dpToPx().toInt()
                        outRect.bottom = 6.7f.dpToPx().toInt()
                    }
                }
            }
        })

        recyclerView.adapter = adapter
    }

    private fun setupBillingClient() {
        purchaseUpdateListener = PurchasesUpdatedListener { billingResult, purchases ->
            handler.post {
                if (
                    billingResult.responseCode == BillingClient.BillingResponseCode.OK &&
                    purchases != null &&
                    selectedProductDetails != null
                ) {
                    for (purchase in purchases) {
                        handlePurchase(purchase)
                    }
                } else if (
                    billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED
                ) {
                    selectedProductDetails = null
                    viewModel.showToast("구매를 취소했습니다.")
                } else {
                    selectedProductDetails = null
                    viewModel.showToast("구매를 하지 못했습니다.\n다시 시도해 주세요.")
                }
            }
        }

        billingClient = BillingClient.newBuilder(requireActivity())
            .enablePendingPurchases()
            .setListener(purchaseUpdateListener)
            .build()

        loadingDialog.show(screenWidth)

        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingServiceDisconnected() {
                viewModel.showToast("인 앱 결제 이용이 불가능 합니다. 다시 시도해 주세요.")
                viewModel.setLoading(false)
            }

            override fun onBillingSetupFinished(billingResult: BillingResult) {
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    queryAndConsumeUnconsumedPurchases()
                } else {
                    viewModel.showToast("인 앱 결제 이용이 불가능 합니다. 다시 시도해 주세요.")
                    viewModel.setLoading(false)
                }
            }
        })
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun queryAvailableCans() {
        val productList = listOf(
            "${requireContext().packageName}.can_35",
            "${requireContext().packageName}.can_55",
            "${requireContext().packageName}.can_105",
            "${requireContext().packageName}.can_350",
            "${requireContext().packageName}.can_550",
            "${requireContext().packageName}.can_1170",
            "${requireContext().packageName}.can_1970"
        )

        val params = QueryProductDetailsParams.newBuilder()
            .setProductList(
                productList.map {
                    QueryProductDetailsParams.Product.newBuilder()
                        .setProductId(it)
                        .setProductType(BillingClient.ProductType.INAPP)
                        .build()
                }
            )
            .build()

        billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList ->
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                handler.post { adapter.addItems(productDetailsList) }
            } else {
                viewModel.showToast("인 앱 결제 이용이 불가능 합니다. 다시 시도해 주세요.")
            }

            viewModel.setLoading(false)
        }
    }

    private fun queryAndConsumeUnconsumedPurchases() {
        val queryPurchaseParams = QueryPurchasesParams.newBuilder()
            .setProductType(BillingClient.ProductType.INAPP)
            .build()

        billingClient.queryPurchasesAsync(
            queryPurchaseParams
        ) { result, purchaseList ->
            if (result.responseCode == BillingClient.BillingResponseCode.OK) {
                if (purchaseList.isNotEmpty()) {
                    for (purchase in purchaseList) {
                        if (!purchase.isAcknowledged) {
                            consumePurchase(purchase) {
                                queryAvailableCans()
                            }
                        }
                    }
                } else {
                    queryAvailableCans()
                }
            }
        }
    }

    private fun consumePurchase(purchase: Purchase, onSuccess: () -> Unit) {
        val params = ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.purchaseToken)
            .build()

        billingClient.consumeAsync(params) { billingResult, _ ->
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                onSuccess()
            }
        }
    }

    private fun handlePurchase(purchase: Purchase) {
        if (
            purchase.purchaseState == Purchase.PurchaseState.PURCHASED &&
            !purchase.isAcknowledged
        ) {
            viewModel.chargeCan(
                title = selectedProductDetails!!.name,
                selectedProductDetails = selectedProductDetails!!,
                purchase = purchase
            ) { chargeCan ->
                handler.post {
                    viewModel.showToast("캔이 충전되었습니다")
                    SharedPreferenceManager.can += chargeCan

                    if (activity != null) {
                        if (activity as? CanChargeActivity != null) {
                            (activity as CanChargeActivity).successIapCharge()
                        } else {
                            requireActivity().finish()
                        }
                    }
                }
            }
        }
    }

    private fun launchPurchaseFlow(productDetails: ProductDetails) {
        val billingFlowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        .setProductDetails(productDetails)
                        .build()
                )
            ).build()

        billingClient.launchBillingFlow(requireActivity(), billingFlowParams)
    }
}
