using System;
using UnityEngine;
using UnityEngine.Purchasing;
using System.Collections;
using UnityEngine.Purchasing.Extension;
using System.Threading.Tasks;

public class IAPManager : MonoBehaviour, IDetailedStoreListener
{
    private static IStoreController storeController;
    private static IExtensionProvider storeExtensionProvider;

    public const string PRODUCT_1000_COINS = "1000_coins";
    public const string PRODUCT_2150_COINS = "2150_coins";
    public const string PRODUCT_4350_COINS = "4350_coins";
    public const string PRODUCT_6700_COINS = "6700_coins";
    public const string PRODUCT_11500_COINS = "11500_coins";

    private CoinWalletSystem coinWalletSystem;
    private StoreUIManager storeUIManager;
    
    [SerializeField] private GameObject purchaseLoadingUI;
    [SerializeField] private GameObject purchaseSuccessUI;
    [SerializeField] private GameObject purchaseFailedUI;

    private void Start()
    {
        coinWalletSystem = CoinWalletSystem.Instance;
        storeUIManager = FindAnyObjectByType<StoreUIManager>();
       

        // Deactivate both UIs initially
        if (storeUIManager != null) storeUIManager.gameObject.SetActive(false);
       

        // Check if in development (Editor) or production (build)
#if UNITY_EDITOR
        // In development, show fake store UI
        
#else
            // In production, show real store UI
            //if (storeUIManager != null) storeUIManager.gameObject.SetActive(true);
#endif

        if (storeController == null)
        {
            InitializePurchasing();
        }
    }

    private void InitializePurchasing()
    {
        if (IsInitialized()) return;

        try
        {
            var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
            builder.AddProduct(PRODUCT_1000_COINS, ProductType.Consumable);
            builder.AddProduct(PRODUCT_2150_COINS, ProductType.Consumable);
            builder.AddProduct(PRODUCT_4350_COINS, ProductType.Consumable);
            builder.AddProduct(PRODUCT_6700_COINS, ProductType.Consumable);
            builder.AddProduct(PRODUCT_11500_COINS, ProductType.Consumable);

            Debug.Log("Initializing Unity Purchasing...");
            UnityPurchasing.Initialize(this, builder);
        }
        catch (Exception e)
        {
            Debug.LogError($"Error initializing IAP: {e.Message}");
        }
    }

    private bool IsInitialized() => storeController != null && storeExtensionProvider != null;

    public void Buy1000Coins() { BuyProduct(PRODUCT_1000_COINS, 1000); }
    public void Buy2150Coins() { BuyProduct(PRODUCT_2150_COINS, 2150); }
    public void Buy4350Coins() { BuyProduct(PRODUCT_4350_COINS, 4350); }
    public void Buy6700Coins() { BuyProduct(PRODUCT_6700_COINS, 6700); }
    public void Buy11500Coins() { BuyProduct(PRODUCT_11500_COINS, 11500); }

    public void BuyProduct(string productID, int coinsToAdd)
    {
        try 
        {
            ShowPurchaseLoading(true);
            Debug.Log($"Attempting to purchase {coinsToAdd} coins");
            
            if (coinWalletSystem == null)
            {
                coinWalletSystem = CoinWalletSystem.Instance;
                if (coinWalletSystem == null)
                {
                    Debug.LogError("CoinWalletSystem is not initialized!");
                    ShowPurchaseResult(false);
                    return;
                }
            }

            // Check if in development (Editor) or production (build)
#if UNITY_EDITOR
            // In development mode, simulate the purchase
            Debug.Log($"Development mode: Simulating purchase of {coinsToAdd} coins");
            SimulatePurchase(coinsToAdd);
#else
            // In production mode, trigger the real IAP purchase flow
            if (IsInitialized())
            {
                Product product = storeController.products.WithID(productID);
                if (product != null && product.availableToPurchase)
                {
                    storeController.InitiatePurchase(product);
                }
                else
                {
                    Debug.LogError("Product not available for purchase: " + productID);
                    ShowPurchaseResult(false);
                }
            }
            else
            {
                Debug.LogError("In-App Purchasing is not initialized.");
                ShowPurchaseResult(false);
            }
#endif
        }
        catch (System.Exception e)
        {
            Debug.LogError($"Error purchasing coins: {e.Message}");
            ShowPurchaseResult(false);
        }
        finally
        {
            ShowPurchaseLoading(false);
        }
    }

    // Add this new method to handle development mode purchases
    private async void SimulatePurchase(int coinsToAdd)
    {
        if (!gameObject.activeInHierarchy)
        {
            gameObject.SetActive(true);
        }

        try
        {
            Debug.Log($"Simulating purchase of {coinsToAdd} coins");
            ShowPurchaseLoading(true);
            
            // Simulate a short delay to mimic network request
            await Task.Delay(1000);
            
            // Add coins directly in development mode
            await coinWalletSystem.AddCoins(coinsToAdd);
            
            // Ensure the game object is still active before showing the result
            if (gameObject != null && gameObject.activeInHierarchy)
            {
                ShowPurchaseResult(true);
            }
            
            Debug.Log($"Development mode: Successfully added {coinsToAdd} coins");
        }
        catch (Exception e)
        {
            Debug.LogError($"Development mode: Failed to simulate purchase: {e.Message}");
            if (gameObject != null && gameObject.activeInHierarchy)
            {
                ShowPurchaseResult(false);
            }
        }
        finally
        {
            if (gameObject != null && gameObject.activeInHierarchy)
            {
                ShowPurchaseLoading(false);
            }
        }
    }

    // Called when a purchase completes
    public void OnPurchaseComplete(Product product)
{
    try
    {
        int coinsToAdd = 0;

        // Determine the number of coins based on the product ID
        if (product.definition.id == PRODUCT_1000_COINS)
        {
            coinsToAdd = 1000;
        }
        else if (product.definition.id == PRODUCT_2150_COINS)
        {
            coinsToAdd = 2150;
        }
        else if (product.definition.id == PRODUCT_4350_COINS)
        {
            coinsToAdd = 4350;
        }
        else if (product.definition.id == PRODUCT_6700_COINS)
        {
            coinsToAdd = 6700;
        }
        else if (product.definition.id == PRODUCT_11500_COINS)
        {
            coinsToAdd = 11500;
        }
        else
        {
            Debug.LogError("Unrecognized product ID.");
            ShowPurchaseResult(false);
            return;
        }

        // Add the coins to the wallet and show the result
        if (coinWalletSystem != null)
        {
            coinWalletSystem.AddCoins(coinsToAdd);
            ShowPurchaseResult(true); // Show success UI
        }
        else
        {
            Debug.LogError("CoinWalletSystem not found!");
            ShowPurchaseResult(false); // Show failure UI
        }
    }
    catch (Exception e)
    {
        Debug.LogError($"Error processing purchase: {e.Message}");
        ShowPurchaseResult(false); // Show failure UI
    }
}


    // Called when a purchase fails
    public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
    {
        Debug.LogError($"Purchase failed for {product.definition.id}: {failureDescription.message}");
        ShowPurchaseResult(false);
    }

    // This method simulates showing the store UI in the development build
    private void ShowFakeStore(string productID, int coinsToAdd)
    {
        // Show the fake store UI or simulate the purchase process
        Debug.Log($"Fake store: ready to purchase {coinsToAdd} coins.");
        // You may trigger the "Buy" button in the fake store UI to simulate a successful purchase
    }

    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {
        if (!gameObject.activeInHierarchy)
        {
            gameObject.SetActive(true);
        }
        
        Debug.Log($"Processing purchase for product: {args.purchasedProduct.definition.id}");
        
        if (coinWalletSystem == null)
        {
            coinWalletSystem = CoinWalletSystem.Instance;
        }

        string productId = args.purchasedProduct.definition.id;
        int coinsToAdd = 0;

        switch (productId)
        {
            case PRODUCT_1000_COINS: coinsToAdd = 1000; break;
            case PRODUCT_2150_COINS: coinsToAdd = 2150; break;
            case PRODUCT_4350_COINS: coinsToAdd = 4350; break;
            case PRODUCT_6700_COINS: coinsToAdd = 6700; break;
            case PRODUCT_11500_COINS: coinsToAdd = 11500; break;
            default: 
                Debug.LogError($"Unrecognized product ID {productId}"); 
                return PurchaseProcessingResult.Complete;
        }

        if (coinsToAdd > 0 && coinWalletSystem != null)
        {
            // Use async/await pattern with Task.Run to handle the async operation
            StartCoroutine(ProcessPurchaseAsync(coinsToAdd));
        }
        else
        {
            Debug.LogError("Failed to add coins: CoinWalletSystem not found or coins amount is 0");
            ShowPurchaseResult(false);
        }

        return PurchaseProcessingResult.Complete;
    }

    private IEnumerator ProcessPurchaseAsync(int coinsToAdd)
    {
        ShowPurchaseLoading(true);
        
        var task = coinWalletSystem.AddCoins(coinsToAdd);
        while (!task.IsCompleted)
        {
            yield return null;
        }

        if (task.Exception == null)
        {
            ShowPurchaseResult(true);
        }
        else
        {
            Debug.LogError($"Failed to process purchase: {task.Exception}");
            ShowPurchaseResult(false);
        }
        
        ShowPurchaseLoading(false);
    }

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        storeController = controller;
        storeExtensionProvider = extensions;
    }

    public void OnInitializeFailed(InitializationFailureReason error)
    {
        Debug.LogError($"IAP initialization failed: {error.ToString()}");
    }

    public void OnInitializeFailed(InitializationFailureReason error, string message)
    {
        Debug.LogError($"IAP initialization failed: {error.ToString()}, Message: {message}");
    }

    // Add the BuyProductID method here
    public void BuyProductID(string productID)
    {
        if (IsInitialized())
        {
            Product product = storeController.products.WithID(productID);
            if (product != null && product.availableToPurchase)
            {
                storeController.InitiatePurchase(product);
            }
            else
            {
                Debug.LogError("Product not available for purchase: " + productID);
            }
        }
        else
        {
            Debug.LogError("In-App Purchasing is not initialized.");
        }
    }

    private void ShowPurchaseLoading(bool show)
    {
        if (purchaseLoadingUI != null)
            purchaseLoadingUI.SetActive(show);
    }

    private void ShowPurchaseResult(bool success)
    {
        if (!gameObject.activeInHierarchy) return;

        if (success && purchaseSuccessUI != null)
        {
            purchaseSuccessUI.SetActive(true);
            StartCoroutine(HideUI(purchaseSuccessUI, 2f));
        }
        else if (!success && purchaseFailedUI != null)
        {
            purchaseFailedUI.SetActive(true);
            StartCoroutine(HideUI(purchaseFailedUI, 2f));
        }
    }

    private IEnumerator HideUI(GameObject ui, float duration)
    {
        if (ui == null) yield break;
        
        yield return new WaitForSeconds(duration);
        
        if (ui != null && gameObject != null && gameObject.activeInHierarchy)
        {
            ui.SetActive(false);
        }
    }

    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    {
        Debug.LogError($"Purchase failed - Product: {product.definition.id}, Reason: {failureReason}");
        ShowPurchaseResult(false);
    }
}
