package com.jpay.apm

import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.browser.customtabs.*
import org.json.JSONObject
import java.lang.ref.WeakReference

/**
 * JPay APM
 */
class JPayAPM {
    
    companion object {
        const val PAY_STATUS_UNPAID = 0
        const val PAY_STATUS_SUCCESS = 1
        const val PAY_STATUS_FAILED = 2
        const val PAY_STATUS_CANCEL = 3
        private const val TAG = "JPayAPM"
    }

    private var mActivityRef: WeakReference<Activity>? = null
    private var mContextRef: WeakReference<Context>? = null
    private var payStatus: Int = PAY_STATUS_UNPAID
    private var payCallback: WeakReference<((JSONObject) -> Unit)?> = WeakReference(null)

    constructor(activity: Activity, context: Context) {
        mActivityRef = WeakReference(activity)
        mContextRef = WeakReference(context)
    }

    /**
     * Execute payment
     * @param payMethod Payment method (only support googlepay)
     * @param payUrl Payment URL
     * @param callback Result callback
     */
    fun exec(payMethod: String, payUrl: String, callback: ((JSONObject) -> Unit)?) {
        Log.d(TAG, "Execute payment: method=$payMethod, url=$payUrl")
        payStatus = PAY_STATUS_UNPAID
        payCallback = WeakReference(callback)

        payByUrl(payUrl)
    }

    /**
     * Handle payment result (main thread callback)
     */
    private fun handlePayResult(status: Int, message: String, orderId: String = "") {
        payStatus = status
        Log.d(TAG, "Payment result: status=$status, msg=$message, orderId=$orderId")

        // Build JSON result
        val result = JSONObject().apply {
            put("status", status)
            put("message", message)
            put("orderId", orderId)
        }

        Handler(Looper.getMainLooper()).post {
            payCallback.get()?.invoke(result)
            payCallback.clear()
        }
    }

    /**
     * Open payment URL
     */
    private fun payByUrl(payUrl: String) {
        val activity = mActivityRef?.get()
        val context = mContextRef?.get()
        if (context == null) {
            handlePayResult(PAY_STATUS_FAILED, "Context is null", "")
            return
        }
        if (activity == null || activity.isFinishing ||
            (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed)) {
            handlePayResult(PAY_STATUS_FAILED, "Activity is null or destroyed", "")
            return
        }

        val uri: Uri
        try {
            uri = Uri.parse(payUrl)
            if (uri.scheme.isNullOrEmpty() || uri.host.isNullOrEmpty()) {
                handlePayResult(PAY_STATUS_FAILED, "Invalid URL format: $payUrl", "")
                return
            }
        } catch (e: Exception) {
            handlePayResult(PAY_STATUS_FAILED, "Failed to parse URL: ${e.message}", "")
            return
        }

        try {
            val intent = CustomTabsIntent.Builder()
                .setShowTitle(true)
                .build()

            intent.launchUrl(activity, uri)
        } catch (e: Exception) {
            Log.e(TAG, "Failed to launch payment URL: $payUrl", e)
            handlePayResult(PAY_STATUS_FAILED, "Failed to launch payment URL: ${e.message}", "")
        }
    }

    /**
     * Trigger payment result (for Scheme callback)
     */
    fun triggerPayResult(status: Int, message: String, orderId: String = "") {
        handlePayResult(status, message, orderId)
    }

    /**
     * Release resources
     */
    fun release() {
        mActivityRef?.clear()
        mContextRef?.clear()
        payCallback.clear()
        payStatus = PAY_STATUS_UNPAID
    }
}