using System;
using System.Collections.Generic;
using YachtDice.Dice;
using YachtDice.Economy;
using YachtDice.Inventory;
using YachtDice.Modifiers.Definition;
using YachtDice.Player;

namespace YachtDice.Shop
{
    public class ShopModel
    {
        private readonly CurrencyBank currencyBank;
        private readonly InventoryModel inventoryModel;
        private readonly DiceCollection diceCollection;
        private readonly HashSet<string> purchasedPermanentIds = new();

        public event Action<IShopItem> OnItemPurchased;

        public ShopModel(CurrencyBank currencyBank, InventoryModel inventoryModel, DiceCollection diceCollection)
        {
            this.currencyBank = currencyBank;
            this.inventoryModel = inventoryModel;
            this.diceCollection = diceCollection;
        }

        public bool CanPurchase(IShopItem item)
        {
            if (item == null) return false;
            if (!currencyBank.CanAfford(item.ShopPrice)) return false;

            if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
                return false;

            return true;
        }

        public bool TryPurchase(IShopItem item)
        {
            if (!CanPurchase(item)) return false;

            if (!currencyBank.Spend(item.ShopPrice)) return false;

            if (!item.IsRepurchasable)
                purchasedPermanentIds.Add(item.Id);

            switch (item)
            {
                case ModifierDefinition modifier:
                    inventoryModel.AddModifier(modifier);
                    break;
                case DieDefinitionSO die:
                    diceCollection.Add(die);
                    break;
            }

            OnItemPurchased?.Invoke(item);
            return true;
        }

        public bool IsPermanentOwned(string itemId) => purchasedPermanentIds.Contains(itemId);

        public ShopItemState GetItemState(IShopItem item)
        {
            if (item == null) return ShopItemState.TooExpensive;

            if (!item.IsRepurchasable && purchasedPermanentIds.Contains(item.Id))
                return ShopItemState.Owned;

            if (!currencyBank.CanAfford(item.ShopPrice))
                return ShopItemState.TooExpensive;

            return item.IsRepurchasable
                ? ShopItemState.RepurchaseAvailable
                : ShopItemState.Available;
        }

        public void LoadPurchasedPermanentIds(IEnumerable<string> ids)
        {
            purchasedPermanentIds.Clear();
            if (ids != null)
                foreach (var id in ids) purchasedPermanentIds.Add(id);
        }

        public HashSet<string> GetPurchasedPermanentIds() => new(purchasedPermanentIds);
    }

    public enum ShopItemState
    {
        Available,
        TooExpensive,
        Owned,
        RepurchaseAvailable,
    }
}
