package com.tt.honeyDue.platform

import android.app.Activity
import android.content.Context
import android.util.Log
import com.android.billingclient.api.*
import com.tt.honeyDue.network.APILayer
import com.tt.honeyDue.network.ApiResult
import com.tt.honeyDue.utils.SubscriptionProducts
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

/**
 * Google Play Billing manager for in-app purchases
 * Handles subscription purchases, verification, and restoration
 */
class BillingManager private constructor(private val context: Context) {

    companion object {
        private const val TAG = "BillingManager"

        @Volatile
        private var INSTANCE: BillingManager? = null

        fun getInstance(context: Context): BillingManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: BillingManager(context.applicationContext).also { INSTANCE = it }
            }
        }
    }

    // Product IDs (must match Google Play Console)
    private val productIDs = SubscriptionProducts.all

    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    // StateFlows for UI observation
    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading

    private val _products = MutableStateFlow<List<ProductDetails>>(emptyList())
    val products: StateFlow<List<ProductDetails>> = _products

    private val _purchasedProductIDs = MutableStateFlow<Set<String>>(emptySet())
    val purchasedProductIDs: StateFlow<Set<String>> = _purchasedProductIDs

    private val _purchaseError = MutableStateFlow<String?>(null)
    val purchaseError: StateFlow<String?> = _purchaseError

    private val _connectionState = MutableStateFlow(false)
    val isConnected: StateFlow<Boolean> = _connectionState

    private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases ->
        when (billingResult.responseCode) {
            BillingClient.BillingResponseCode.OK -> {
                purchases?.forEach { purchase ->
                    handlePurchase(purchase)
                }
            }
            BillingClient.BillingResponseCode.USER_CANCELED -> {
                Log.d(TAG, "User canceled purchase")
                _purchaseError.value = null // Not really an error
            }
            else -> {
                val errorMessage = "Purchase failed: ${billingResult.debugMessage}"
                Log.e(TAG, errorMessage)
                _purchaseError.value = errorMessage
            }
        }
        _isLoading.value = false
    }

    private val billingClient: BillingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases()
        .build()

    init {
        Log.d(TAG, "BillingManager initialized")
    }

    /**
     * Connect to Google Play Billing
     */
    fun startConnection(onSuccess: () -> Unit = {}, onError: (String) -> Unit = {}) {
        if (billingClient.isReady) {
            Log.d(TAG, "Already connected to billing")
            onSuccess()
            return
        }

        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    Log.d(TAG, "Billing connection successful")
                    _connectionState.value = true
                    onSuccess()
                } else {
                    val error = "Billing setup failed: ${billingResult.debugMessage}"
                    Log.e(TAG, error)
                    _connectionState.value = false
                    onError(error)
                }
            }

            override fun onBillingServiceDisconnected() {
                Log.w(TAG, "Billing service disconnected, will retry")
                _connectionState.value = false
                // Retry connection after a delay
                scope.launch {
                    kotlinx.coroutines.delay(3000)
                    startConnection(onSuccess, onError)
                }
            }
        })
    }

    /**
     * Query available subscription products from Google Play
     */
    suspend fun loadProducts() {
        if (!billingClient.isReady) {
            Log.w(TAG, "Billing client not ready, cannot load products")
            return
        }

        _isLoading.value = true

        try {
            val productList = productIDs.map { productId ->
                QueryProductDetailsParams.Product.newBuilder()
                    .setProductId(productId)
                    .setProductType(BillingClient.ProductType.SUBS)
                    .build()
            }

            val params = QueryProductDetailsParams.newBuilder()
                .setProductList(productList)
                .build()

            val result = billingClient.queryProductDetails(params)

            if (result.billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                _products.value = result.productDetailsList ?: emptyList()
                Log.d(TAG, "Loaded ${_products.value.size} products")

                // Log product details for debugging
                _products.value.forEach { product ->
                    Log.d(TAG, "Product: ${product.productId} - ${product.title}")
                    product.subscriptionOfferDetails?.forEach { offer ->
                        Log.d(TAG, "  Offer: ${offer.basePlanId} - ${offer.pricingPhases.pricingPhaseList.firstOrNull()?.formattedPrice}")
                    }
                }
            } else {
                Log.e(TAG, "Failed to load products: ${result.billingResult.debugMessage}")
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error loading products", e)
        } finally {
            _isLoading.value = false
        }
    }

    /**
     * Launch purchase flow for a subscription
     */
    fun launchPurchaseFlow(
        activity: Activity,
        productDetails: ProductDetails,
        onSuccess: () -> Unit = {},
        onError: (String) -> Unit = {}
    ) {
        if (!billingClient.isReady) {
            onError("Billing not ready")
            return
        }

        val offerToken = productDetails.subscriptionOfferDetails?.firstOrNull()?.offerToken
        if (offerToken == null) {
            onError("No offer available for this product")
            return
        }

        _isLoading.value = true
        _purchaseError.value = null

        val productDetailsParams = BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()

        val billingFlowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(listOf(productDetailsParams))
            .build()

        val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

        if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
            _isLoading.value = false
            val error = "Failed to launch purchase: ${billingResult.debugMessage}"
            Log.e(TAG, error)
            onError(error)
        }
        // Note: Success/failure is handled in purchasesUpdatedListener
    }

    /**
     * Handle a completed purchase
     */
    private fun handlePurchase(purchase: Purchase) {
        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            Log.d(TAG, "Purchase successful: ${purchase.products}")

            // Verify with backend and acknowledge
            scope.launch {
                try {
                    // Verify purchase with backend
                    val verified = verifyPurchaseWithBackend(
                        purchaseToken = purchase.purchaseToken,
                        productId = purchase.products.firstOrNull() ?: ""
                    )

                    if (verified) {
                        // Acknowledge if not already acknowledged
                        if (!purchase.isAcknowledged) {
                            acknowledgePurchase(purchase.purchaseToken)
                        }

                        // Update local state
                        _purchasedProductIDs.value = _purchasedProductIDs.value + purchase.products.toSet()

                        // Refresh subscription status from backend (updates DataManager which derives tier)
                        APILayer.getSubscriptionStatus(forceRefresh = true)

                        Log.d(TAG, "Purchase verified and acknowledged")
                    } else {
                        _purchaseError.value = "Failed to verify purchase with server"
                    }
                } catch (e: Exception) {
                    Log.e(TAG, "Error handling purchase", e)
                    _purchaseError.value = "Error processing purchase: ${e.message}"
                }
            }
        } else if (purchase.purchaseState == Purchase.PurchaseState.PENDING) {
            Log.d(TAG, "Purchase pending: ${purchase.products}")
            // Handle pending purchases (e.g., waiting for payment method)
        }
    }

    /**
     * Verify purchase with backend server
     */
    private suspend fun verifyPurchaseWithBackend(purchaseToken: String, productId: String): Boolean {
        return try {
            val result = APILayer.verifyAndroidPurchase(
                purchaseToken = purchaseToken,
                productId = productId
            )

            when (result) {
                is ApiResult.Success -> {
                    Log.d(TAG, "Backend verification successful: tier=${result.data.tier}")
                    result.data.success
                }
                is ApiResult.Error -> {
                    Log.e(TAG, "Backend verification failed: ${result.message}")
                    false
                }
                else -> false
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error verifying purchase with backend", e)
            false
        }
    }

    /**
     * Acknowledge purchase (required by Google Play - purchases refund after 3 days if not acknowledged)
     */
    private suspend fun acknowledgePurchase(purchaseToken: String) {
        val params = AcknowledgePurchaseParams.newBuilder()
            .setPurchaseToken(purchaseToken)
            .build()

        val result = billingClient.acknowledgePurchase(params)

        if (result.responseCode == BillingClient.BillingResponseCode.OK) {
            Log.d(TAG, "Purchase acknowledged")
        } else {
            Log.e(TAG, "Failed to acknowledge purchase: ${result.debugMessage}")
        }
    }

    /**
     * Restore purchases (check for existing subscriptions)
     */
    suspend fun restorePurchases(): Boolean {
        if (!billingClient.isReady) {
            Log.w(TAG, "Billing client not ready, cannot restore purchases")
            return false
        }

        _isLoading.value = true

        return try {
            val params = QueryPurchasesParams.newBuilder()
                .setProductType(BillingClient.ProductType.SUBS)
                .build()

            val result = billingClient.queryPurchasesAsync(params)

            if (result.billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                val activePurchases = result.purchasesList.filter {
                    it.purchaseState == Purchase.PurchaseState.PURCHASED
                }

                Log.d(TAG, "Found ${activePurchases.size} active purchases")

                if (activePurchases.isNotEmpty()) {
                    // Update purchased products
                    _purchasedProductIDs.value = activePurchases
                        .flatMap { it.products }
                        .toSet()

                    // Verify each with backend
                    activePurchases.forEach { purchase ->
                        verifyPurchaseWithBackend(
                            purchaseToken = purchase.purchaseToken,
                            productId = purchase.products.firstOrNull() ?: ""
                        )
                    }

                    // Refresh subscription status from backend (updates DataManager which derives tier)
                    APILayer.getSubscriptionStatus(forceRefresh = true)

                    true
                } else {
                    Log.d(TAG, "No active purchases to restore")
                    // Still fetch subscription status from backend to get free tier limits
                    APILayer.getSubscriptionStatus(forceRefresh = true)
                    false
                }
            } else {
                Log.e(TAG, "Failed to query purchases: ${result.billingResult.debugMessage}")
                false
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error restoring purchases", e)
            false
        } finally {
            _isLoading.value = false
        }
    }

    /**
     * Clear error state
     */
    fun clearError() {
        _purchaseError.value = null
    }

    /**
     * Get formatted price for a product
     */
    fun getFormattedPrice(productDetails: ProductDetails): String? {
        return productDetails.subscriptionOfferDetails
            ?.firstOrNull()
            ?.pricingPhases
            ?.pricingPhaseList
            ?.firstOrNull()
            ?.formattedPrice
    }

    /**
     * Calculate savings percentage for annual vs monthly
     */
    fun calculateAnnualSavings(monthly: ProductDetails?, annual: ProductDetails?): Int? {
        if (monthly == null || annual == null) return null

        val monthlyPrice = monthly.subscriptionOfferDetails
            ?.firstOrNull()
            ?.pricingPhases
            ?.pricingPhaseList
            ?.firstOrNull()
            ?.priceAmountMicros ?: return null

        val annualPrice = annual.subscriptionOfferDetails
            ?.firstOrNull()
            ?.pricingPhases
            ?.pricingPhaseList
            ?.firstOrNull()
            ?.priceAmountMicros ?: return null

        // Calculate what 12 months would cost vs annual price
        val yearlyAtMonthlyRate = monthlyPrice * 12
        val savings = ((yearlyAtMonthlyRate - annualPrice).toDouble() / yearlyAtMonthlyRate * 100).toInt()

        return if (savings > 0) savings else null
    }

    /**
     * Get product by ID
     */
    fun getProduct(productId: String): ProductDetails? {
        return _products.value.find { it.productId == productId }
    }

    /**
     * Get monthly product
     */
    fun getMonthlyProduct(): ProductDetails? {
        return _products.value.find { it.productId == SubscriptionProducts.MONTHLY }
    }

    /**
     * Get annual product
     */
    fun getAnnualProduct(): ProductDetails? {
        return _products.value.find { it.productId == SubscriptionProducts.ANNUAL }
    }

    /**
     * Check if user has an active subscription
     */
    fun hasActiveSubscription(): Boolean {
        return _purchasedProductIDs.value.isNotEmpty()
    }
}
