import { getComponentViewBindingId } from "./helpers";

export function findComponentsWithStripePaymentAction(data, result = []) {
  if (!Array.isArray(data)) data = [data];
  for (const item of data) {
    if ("components" in item) {
      findComponentsWithStripePaymentAction(item.components, result);
    }
    if ("children" in item) {
      findComponentsWithStripePaymentAction(item.children, result);
    }
    if ("props" in item && item.name == "StripePaymentButton") {
      result.push(item);
    }
  }
  return result;
}

export const generateStripePaymentImport = (fragment, configuration) => {
  if (findComponentsWithStripePaymentAction(fragment).length == 0) return "";
  return `
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.provider.MediaStore
import android.util.Log
import android.widget.VideoView
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import ${configuration.packageName}.extensions.viewBinding
import com.stripe.android.ApiResultCallback
import com.stripe.android.CustomerSession
import com.stripe.android.EphemeralKeyProvider
import com.stripe.android.EphemeralKeyUpdateListener
import com.stripe.android.PaymentConfiguration
import com.stripe.android.PaymentIntentResult
import com.stripe.android.PaymentSession
import com.stripe.android.PaymentSessionConfig
import com.stripe.android.PaymentSessionData
import com.stripe.android.Stripe
import com.stripe.android.model.ConfirmPaymentIntentParams
import com.stripe.android.model.StripeIntent
import com.stripe.android.view.PaymentMethodsActivityStarter
import org.jetbrains.annotations.Nullable
 `;
};

export const generateStripePaymentField = (fragment, configuration) => {
  if (findComponentsWithStripePaymentAction(fragment).length == 0) return "";
  return `
  private  var stripe: Stripe?=null
  private val TAG:String="MainActivity"
  private  var paymentMethodId:String?=null
  private  var clientSecret:String?=null
  private  var paymentSession: PaymentSession?=null
  private var ephemeralKeyRawJson: String? = null

 `;
};

export const generateStripePaymentBinding = (fragment, configuration) => {
  if (findComponentsWithStripePaymentAction(fragment).length == 0) return "";

  const content = [];

  content.push(`getStripeData(userId.toString(), amount, "")`);
  const stripePayment = findComponentsWithStripePaymentAction(fragment);
  for (const element of stripePayment) {
    content.push(
      `binding.${getComponentViewBindingId(
        element
      )}.setOnClickListener(View.OnClickListener {
            makePayment()
        })`
    );
  }
  return content.join("\n");
};

export const generateStripePaymentFunctions = (fragment, configuration) => {
  if (findComponentsWithStripePaymentAction(fragment).length == 0) return "";
  return `
   private fun getStripeData(userID: String, amount: String, currency: String) {

        baasViewModel.getStripeData(userID, amount, currency).observe(viewLifecycleOwner) {

            when (it.status) {
                Status.ERROR -> {
                }
                Status.LOADING -> {}
                Status.SUCCESS -> {
                    ephemeralKeyRawJson = it.data?.ephemeralKeyRaw
                    initializeCustomerSession(requireContext(), ephemeralKeyRawJson ?: "")

                }
            }
        }
    }


    fun initializeCustomerSession(context: Context?, ephemeralKeyRawJson:String){

        context?.let {context->

            CustomerSession.initCustomerSession(
                context,
                createEphemeralKeyProvider(ephemeralKeyRawJson)
            )
        }

    }

    private fun createEphemeralKeyProvider(ephemeralKeyRawJson: String): EphemeralKeyProvider {
        return object : EphemeralKeyProvider {
            override fun createEphemeralKey(
                apiVersion: String,
                keyUpdateListener: EphemeralKeyUpdateListener
            ) {
                keyUpdateListener.onKeyUpdate(ephemeralKeyRawJson)
            }
        }
    }

    fun endCustomerSession(){
        CustomerSession.endCustomerSession()
    }


    private fun makePayment() {
        // need to call api to get client secret key (you need to pass amount, currency, customer id to get client secret key)
        ephemeralKeyRawJson?.let { initializeCustomerSession(activity, it) }
        paymentSession = PaymentSession(
            this, 
            createPaymentSessionConfig()
        )

        paymentSession?.init(createPaymentSessionListener())

        PaymentMethodsActivityStarter(this)
            .startForResult(
                PaymentMethodsActivityStarter.Args.Builder()
                    .build()
            )
    }

    private fun createPaymentSessionListener(): PaymentSession.PaymentSessionListener {
        return object : PaymentSession.PaymentSessionListener {
            override fun onCommunicatingStateChanged(isCommunicating: Boolean) {
                Log.e(TAG,"onCommunicatingStateChanged "+isCommunicating)
            }

            override fun onError(errorCode: Int, errorMessage: String) {
                Log.e(TAG,"onError "+errorCode+"  "+errorMessage)
            }

            override fun onPaymentSessionDataChanged(data: PaymentSessionData) {
                Log.e(TAG,"onPaymentSessionDataChanged "+data.isPaymentReadyToCharge+"  "+data)

                if (data.isPaymentReadyToCharge){
                    paymentMethodId?.let {
                        clientSecret?.let { it1 ->
                            confirmPayment(
                                it1, it
                            )
                        }
                    }
                }
            }
        }
    }

    private fun createPaymentSessionConfig(): PaymentSessionConfig {
        return PaymentSessionConfig.Builder()
            .setShippingMethodsRequired(false)
            .setShippingInfoRequired(false)
            .build()
    }

    private fun confirmPayment(
        clientSecret: String,
        paymentMethodId: String
    ) {

        Stripe
        stripe = Stripe(
            requireContext(),
            PaymentConfiguration.getInstance(requireContext()).publishableKey)

        stripe?.confirmPayment(
            this,
            ConfirmPaymentIntentParams.createWithPaymentMethodId(
                paymentMethodId,
                clientSecret
            )
        )

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == PaymentMethodsActivityStarter.REQUEST_CODE) {

            data?.let {
                val result = PaymentMethodsActivityStarter.Result.fromIntent(data)

                val paymentMethod = result?.paymentMethod
                Log.e(TAG, "paymentMethodId : " + paymentMethod?.id)
                paymentMethodId = paymentMethod?.id.toString()
                paymentSession?.handlePaymentData(requestCode, resultCode, it)
            }
        }else {
            stripe?.onPaymentResult(
                requestCode,
                data,
                object : ApiResultCallback<PaymentIntentResult> {
                    override fun onSuccess(result: PaymentIntentResult) {
                        val paymentIntent = result.intent
                        when (paymentIntent.status) {
                            StripeIntent.Status.Succeeded -> {
                                Log.e(TAG, "Payment Success")
                            }
                            StripeIntent.Status.RequiresPaymentMethod -> {
                                Log.e(
                                    TAG,
                                    "Payment Failed " + paymentIntent.lastPaymentError?.message
                                )
                            }
                            else -> {
                                Log.e(TAG, "Payment status unknown " + paymentIntent.status)

                            }
                        }
                    }

                    override fun onError(e: Exception) {
                        Log.e(TAG, "Payment Error " + e.localizedMessage)
                    }
                })
        }
    }
 `;
};
