using CanteenContracts.BindingModels;
using CanteenContracts.View;
using CanteenDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CanteenDatabaseImplement.Models
{
    //public class Dish : IDishModel
    //{
    //    public int Id { get; private set; }
    //    [Required]
    //    public string DishName { get; private set; } = string.Empty;
    //    [Required]
    //    public double Cost { get; private set; }
    //    [Required]
    //    public int ManagerId { get; private set; }
    //    private Dictionary<int, (IProductModel, int)>? _dishProduct = null;
    //    public Dictionary<int, (IProductModel, int)> DishProduct
    //    {
    //        get
    //        {
    //            if (_dishProduct == null)
    //            {
    //                _dishProduct = Product
    //                        .ToDictionary(recPC => recPC.ProductId, recPC => (recPC.Product as IProductModel, recPC.CountProductProduct));
    //            }
    //            return _dishProduct;
    //        }
    //    }
    //    [ForeignKey("DishId")]
    //    public virtual List<DishProduct> Product { get; set; } = new();
    //    public static Dish? Create(CanteenDatabase context, DishBindingModel model)
    //    {
    //        return new Dish()
    //        {
    //            Id = model.Id,
    //            DishName = model.DishName,
    //            Cost = model.Cost,
    //            Product = model.DishProduct.Select(x => new DishProduct
    //            {
    //                Product = context.Product.First(y => y.Id == x.Key)
    //            }).ToList()
    //        };
    //    }

    //    public void Update(DishBindingModel model)
    //    {
    //        DishName = model.DishName;
    //        Cost = model.Cost;
    //    }

    //    public DishViewModel GetViewModel => new()
    //    {
    //        Id = Id,
    //        DishName = DishName,
    //        Cost = Cost,
    //        DishProduct = DishProduct,
    //        ManagerId = ManagerId
    //    };

    //    public Dictionary<int, (IProductModel, int)> DishProduct => throw new NotImplementedException();

    //    public void UpdateProduct(CanteenDatabase context, DishBindingModel model)
    //    {
    //        var dishProduct = context.DishProduct.Where(record => record.ProductId == model.Id).ToList();
    //        if (dishProduct != null && dishProduct.CountProduct > 0)
    //        {
    //            context.DishProduct.RemoveRange(dishProduct.Where(record => !model.DishProduct.ContainsKey(record.ProductId)));
    //            context.SaveChanges();
    //        }

    //        var product = context.Product.First(x => x.Id == Id);
    //        foreach (var pc in model.DishProduct)
    //        {
    //            context.DishProduct.Add(new DishProduct
    //            {
    //                Product = product,
    //                Dish = context.Dishes.First(x => x.Id == pc.Key),
    //            });
    //            context.SaveChanges();
    //        }

    //        _dishProduct = null;
    //    }
    //}
    public class Dish : IDishModel
    {
        public int Id { get; set; }
        [Required]
        public string DishName { get; set; } = string.Empty;
        [Required]
        public double Price { get; set; }
        [Required]
        public int ManagerId { get; set; }

        private Dictionary<int, (IProductModel, int)>? _dishProducts = null;
        [NotMapped]
        public Dictionary<int, (IProductModel, int)> DishProducts
        {
            get
            {
                if (_dishProducts == null)
                {
                    _dishProducts = Products
                        .ToDictionary(recDP => recDP.DishId, recDP => (recDP.Product as IProductModel, recDP.CountProducts));
                }
                return _dishProducts;
            }
        }

        [ForeignKey("DishId")]
        public virtual List<DishProduct> Products { get; set; } = new();
        [ForeignKey("DishId")]
        public virtual List<OrderDish> Orders { get; set; } = new();
        public virtual Manager Manager { get; set; }

        public static Dish Create(CanteenDatabase context, DishBindingModel model)
        {
            return new Dish
            {
                Id = model.Id,
                DishName = model.DishName,
                Price = model.Price,
                ManagerId = model.ManagerId,
                Products = model.DishProducts.Select(x => new DishProduct
                {
                    Product = context.Products.First(y => y.Id == x.Key),
                    CountProducts = x.Value.Item2
                }).ToList()
            };
        }

        public void Update(DishBindingModel model)
        {
            DishName = model.DishName;
            Price = model.Price;
            ManagerId = model.ManagerId;
        }

        public DishViewModel GetViewModel => new()
        {
            Id = Id,
            DishName = DishName,
            Price = Price,
            ManagerId = ManagerId,
            DishProducts = DishProducts
        };


        public void UpdateDishProduct(CanteenDatabase context, DishBindingModel model)
        {
            var dishProduct = context.DishProduct.Where(rec => rec.DishId == model.Id).ToList();
            if (dishProduct != null && (dishProduct.Count > 0))
            {
                context.DishProduct.RemoveRange(dishProduct.Where(rec => !model.DishProducts.ContainsKey(rec.ProductId)));
                context.SaveChanges();
                foreach (var updateProduct in dishProduct)
                {
                    updateProduct.CountProducts = model.DishProducts[updateProduct.ProductId].Item2;
                    model.DishProducts.Remove(updateProduct.ProductId);
                }
                context.SaveChanges();
            }
            var dish = context.Dishes.First(x => x.Id == Id);
            foreach (var dp in model.DishProducts)
            {
                context.DishProduct.Add(new DishProduct
                {
                    Dish = dish,
                    Product = context.Products.First(x => x.Id == dp.Key),
                    CountProducts = dp.Value.Item2
                });
                context.SaveChanges();
            }
            _dishProducts = null;
        }
    }
}
