using SoftwareInstallationContracts.BindingModels;
using SoftwareInstallationContracts.SearchModels;
using SoftwareInstallationContracts.StoragesContracts;
using SoftwareInstallationContracts.ViewModels;
using SoftwareInstallationDataModels;
using SoftwareInstallationDataModels.Models;

namespace SoftwareInstallationFileImplement
{
    public class ShopStorage : IShopStorage
    {
        private readonly DataFileSingleton _source;
        public ShopStorage()
        {
            _source = DataFileSingleton.GetInstance();
        }

        public ShopViewModel? Delete(ShopBindingModel model)
        {
            var element = _source.Shops.FirstOrDefault(x => x.Id == model.Id);
            if (element != null)
            {
                _source.Shops.Remove(element);
                _source.SaveShops();
                return element.GetViewModel;
            }
            return null;
        }

        public ShopViewModel? GetElement(ShopSearchModel model)
        {
            if (!model.Id.HasValue)
            {
                return null;
            }
            return _source.Shops.FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)?.GetViewModel;
        }

        public List<ShopViewModel> GetFilteredList(ShopSearchModel model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                return new();
            }
            return _source.Shops
                .Select(x => x.GetViewModel)
                .Where(x => x.Name.Contains(model.Name ?? string.Empty))
                .ToList();
        }

        public List<ShopViewModel> GetFullList()
        {
            return _source.Shops
                .Select(shop => shop.GetViewModel)
                .ToList();
        }

        public ShopViewModel? Insert(ShopBindingModel model)
        {
            model.Id = _source.Shops.Count > 0 ? _source.Shops.Max(x => x.Id) + 1 : 1;
            var newShop = Shop.Create(model);
            if (newShop == null)
            {
                return null;
            }
            _source.Shops.Add(newShop);
            _source.SaveShops();
            return newShop.GetViewModel;
        }

        public ShopViewModel? Update(ShopBindingModel model)
        {
            var shop = _source.Shops.FirstOrDefault(x => x.Id == model.Id);
            if (shop == null)
            {
                return null;
            }
            shop.Update(model);
            _source.SaveShops();
            return shop.GetViewModel;
        }

        public bool SellPackages(IPackageModel package, int needCount)
        {
            var resultCount = _source.Shops
                .Select(shop => shop.Packages
                .FirstOrDefault(x => x.Key == package.Id).Value.Item2)
                .Sum();

            if (resultCount >= needCount)
            {
                return false;
            }
            foreach (var shop in _source.Shops.Where(shop => shop.Packages.ContainsKey(package.Id)))
            {
                var tuple = shop.Packages[package.Id];
                var diff = Math.Min(tuple.Item2, needCount);
                shop.Packages[package.Id] = (tuple.Item1, tuple.Item2 - diff);
                
                needCount -= diff;
                if (needCount <= 0)
                {
                    return true;
                }
            }
                
            return true;
        }
    }
}
