using IceCreamShopContracts.StoragesContracts;
using IceCreamShopContracts.BindingModels;
using IceCreamShopContracts.SearchModels;
using IceCreamShopContracts.ViewModels;
using AbstractIceCreamShopDataModels.Models;
using IceCreamShopFileImplement.Models;
using System.Reflection.Metadata;
using System.Reflection;

namespace IceCreamShopFileImplement.Implements
{
    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)
            {
                return null;
            }
            source.Shops.Remove(element);
            source.SaveShops();
            return element.GetViewModel;
        }

        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(x => x.GetViewModel).ToList();
        }

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

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

        public bool SellIceCreams(IIceCreamModel model, int count)
        {
            var iceCream = source.IceCreams.FirstOrDefault(x => x.Id == model.Id);

            var countStore = count;

            if (iceCream == null)
            {
                return false;
            }

            foreach (var shop in source.Shops)
            {
                foreach (var icecream in shop.ShopIceCreams)
                {
                    if (icecream.Value.Item1.Id == iceCream.Id)
                    {
                        count -= icecream.Value.Item2;
                    }
                    if (count <= 0)
                    {
                        break;
                    }
                }
            }

            if (count > 0)
            {
                return false;
            }

            count = countStore;

            for (int i = 0; i < source.Shops.Count; i++)
            {
                var shop = source.Shops[i];
                var icecreams = shop.ShopIceCreams;

                foreach (var icecream in icecreams.Where(x => x.Value.Item1.Id == iceCream.Id))
                {
                    var min = Math.Min(icecream.Value.Item2, count);
                    icecreams[icecream.Value.Item1.Id] = (icecream.Value.Item1, icecream.Value.Item2 - min);
                    count -= min;

                    if (count <= 0)
                    {
                        break;
                    }
                }

                shop.Update(new ShopBindingModel
                {
                    Id = shop.Id,
                    Name = shop.Name,
                    Adress = shop.Adress,
                    OpeningDate = shop.OpeningDate,
                    IceCreamMaxCount = shop.IceCreamMaxCount,
                    ShopIceCreams = icecreams
                });
                source.SaveShops();
            }
            if (count > 0)
            {
                return false;
            }
            return true;
        }
    }
}
