using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using RudderSdk.Core.Models.Stores;
using UnityEngine;
using RudderSdk.Unity;

namespace RudderSdk.Unity.Samples
{
  public class StoreInventorySample : MonoBehaviour
  {
    [SerializeField] string nickname = "Player";
    [SerializeField] string region = "global";
    [SerializeField] string language = "en";

    readonly SamplePage _page = new SamplePage(
      "Store & Inventory",
      "List store offers, purchase one, then refresh wallets and inventory.");

    IReadOnlyList<Store> _stores = Array.Empty<Store>();

    void Start()
    {
      _page.Run(this, async () =>
      {
        await Rudder.Initialize().Auth.LoginWithDeviceAsync(region, language, nickname);
        _page.Log("Signed in");
        await LoadCatalog();
        await LoadInventory();
      });
    }

    void OnGUI()
    {
      _page.Draw(() =>
      {
        GUILayout.BeginHorizontal();
        if (_page.Button("Refresh catalog"))
          _page.Run(this, LoadCatalog);
        if (_page.Button("Refresh inventory"))
          _page.Run(this, LoadInventory);
        GUILayout.EndHorizontal();

        foreach (var store in _stores)
        {
          GUILayout.Space(6f);
          _page.Label(store.Name + "  (" + store.Slug + ")");
          if (store.Offers == null || store.Offers.Count == 0)
          {
            _page.Label("  no offers");
            continue;
          }

          foreach (var offer in store.Offers)
          {
            var slug = store.Slug;
            var offerId = offer.Id;
            var name = string.IsNullOrEmpty(offer.Name) ? offer.Id : offer.Name;
            var price = offer.Price == null ? "free" : offer.Price.Amount + " " + offer.Price.Currency;
            if (_page.Button("Buy " + name + " — " + price))
              _page.Run(this, () => Buy(slug, offerId, name));
          }
        }
      });
    }

    async Task LoadCatalog()
    {
      var client = Rudder.Initialize();
      _page.Log("Stores.ListAsync()");
      var stores = await client.Stores.ListAsync();
      _stores = stores ?? Array.Empty<Store>();
      _page.SetStatus(_stores.Count == 0 ? "No stores" : "Loaded " + _stores.Count + " store(s)");
    }

    async Task Buy(string storeSlug, string offerId, string name)
    {
      var client = Rudder.Initialize();
      _page.Log("Stores.PurchaseAsync(" + storeSlug + ", " + offerId + ")");
      var response = await client.Stores.PurchaseAsync(storeSlug, offerId);
      if (response != null && response.Success != true)
        throw new InvalidOperationException(response.Error ?? "Purchase rejected");

      _page.SetStatus("Purchased " + name);
      await LoadInventory();
    }

    async Task LoadInventory()
    {
      var client = Rudder.Initialize();
      _page.Log("Inventory.GetAsync() / Player.GetProfileAsync()");
      var items = await client.Inventory.GetAsync();
      var profile = await client.Player.GetProfileAsync();

      var text = new StringBuilder();
      text.Append("Wallets:");
      if (profile?.Wallets == null || profile.Wallets.Count == 0)
      {
        text.Append(" none");
      }
      else
      {
        foreach (var wallet in profile.Wallets)
          text.Append("\n  " + wallet.Balance + " " + wallet.Currency);
      }

      text.Append("\n\nInventory:");
      if (items == null || items.Count == 0)
      {
        text.Append(" empty");
      }
      else
      {
        foreach (var item in items)
        {
          var name = string.IsNullOrEmpty(item.NameOverride) ? item.Slug : item.NameOverride;
          text.Append("\n  " + name + " × " + item.Amount);
        }
      }

      _page.SetOutput(text.ToString());
    }
  }
}
