using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;

namespace CurrencyManager
{
    public class WalletTests
    {
        private Wallet wallet;
        private Currency currency1;
        private Currency currency2;

        [SetUp]
        public void Setup()
        {
            // Create a Wallet instance and initialize currencies.
            wallet = new GameObject().AddComponent<Wallet>();
            currency1 = ScriptableObject.CreateInstance<Currency>();
            currency2 = ScriptableObject.CreateInstance<Currency>();

            currency1.ExchangeRateToBaseCurrency = 1; // 1:1
            currency2.ExchangeRateToBaseCurrency = 0.001f; // 1:1000
        }

        [Test]
        public void AddCurrencyTest()
        {
            wallet.AddCurrency(currency1, 100);
            wallet.AddCurrency(currency2, 200);

            Assert.AreEqual(100, wallet.GetCurrencyBalance(currency1));
            Assert.AreEqual(200, wallet.GetCurrencyBalance(currency2));
        }

        [Test]
        public void SubtractCurrencyTest()
        {
            wallet.AddCurrency(currency1, 100);
            wallet.AddCurrency(currency2, 200);

            wallet.SubtractCurrency(currency1, 50);
            wallet.SubtractCurrency(currency2, 150);

            Assert.AreEqual(50, wallet.GetCurrencyBalance(currency1));
            Assert.AreEqual(50, wallet.GetCurrencyBalance(currency2));
        }

        [Test]
        public void AddCurrenciesTest()
        {
            List<Wallet.CurrencyAmount> currencyAmountsToAdd = new List<Wallet.CurrencyAmount>
            {
                new Wallet.CurrencyAmount { currency = currency1, amount = 100 },
                new Wallet.CurrencyAmount { currency = currency2, amount = 200 }
            };
            wallet.AddCurrencies(currencyAmountsToAdd);

            Assert.AreEqual(100, wallet.GetCurrencyBalance(currency1));
            Assert.AreEqual(200, wallet.GetCurrencyBalance(currency2));
        }

        [Test]
        public void SubtractCurrenciesTest()
        {
            wallet.AddCurrency(currency1, 100);
            wallet.AddCurrency(currency2, 200);

            List<Wallet.CurrencyAmount> currencyAmountsToSubtract = new List<Wallet.CurrencyAmount>
            {
                new Wallet.CurrencyAmount { currency = currency1, amount = 50 },
                new Wallet.CurrencyAmount { currency = currency2, amount = 150 }
            };
            wallet.SubtractCurrencies(currencyAmountsToSubtract);

            Assert.AreEqual(50, wallet.GetCurrencyBalance(currency1));
            Assert.AreEqual(50, wallet.GetCurrencyBalance(currency2));
        }

        [Test]
        public void GetInsufficientCurrenciesTest()
        {
            wallet.AddCurrency(currency1, 100);
            wallet.AddCurrency(currency2, 200);

            List<Wallet.CurrencyAmount> currencyAmountsToSubtract = new List<Wallet.CurrencyAmount>
            {
                new Wallet.CurrencyAmount { currency = currency1, amount = 50 },
                new Wallet.CurrencyAmount { currency = currency2, amount = 150 }
            };
            Assert.IsEmpty(wallet.GetInsufficientCurrencies(currencyAmountsToSubtract));

            List<Wallet.CurrencyAmount> currencyAmountsCannotSubtract = new List<Wallet.CurrencyAmount>
            {
                new Wallet.CurrencyAmount { currency = currency1, amount = 150 },
                new Wallet.CurrencyAmount { currency = currency2, amount = 250 }
            };

            List<Currency> insufficientCurrencies = wallet.GetInsufficientCurrencies(currencyAmountsCannotSubtract);
            Assert.AreEqual(2, insufficientCurrencies.Count);
            Assert.Contains(currency1, insufficientCurrencies);
            Assert.Contains(currency2, insufficientCurrencies);
        }

        [Test]
        public void ExchangeCurrencyTest()
        {
            wallet.AddCurrency(currency1, 100);
            wallet.AddCurrency(currency2, 0);

            bool exchangeSuccessful = wallet.ExchangeCurrency(currency1, currency2, 50);

            Assert.IsTrue(exchangeSuccessful);
            Assert.AreEqual(50, wallet.GetCurrencyBalance(currency1));
            Assert.AreEqual(50000, wallet.GetCurrencyBalance(currency2), 0.01f);
        }
    }
}
