using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.ViewModels;
using DataModels.Enums;
using DataModels.Models;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace DatabaseImplement.Models
{
	public class Purchase : IPurchase
	{
		public Guid Id { get; set; }
		[Required]
		public DateTime DatePurchase { get; set; }
        [Required]
		public Guid UserId { get; set; }
        [Required]
		public PurchaseStatus Status { get; private set; } = PurchaseStatus.Unknown;
        private Dictionary<Guid, (IProduct, int)>? _purchaseProducts = null;
        public virtual User? User { get; set; }
		[DataMember]
        [NotMapped]
        public Dictionary<Guid, (IProduct, int)> PurchaseProducts
        {
            get
            {
                if (_purchaseProducts == null)
                {
                    _purchaseProducts = Products.ToDictionary(e => e.ProductId, e => (e.Product as IProduct, e.Count));
                }
                return _purchaseProducts;
            }
            set { }
        }
		[ForeignKey("PurchaseId")]
		public virtual List<PurchaseProducts> Products { get; set; } = new();
        public static Purchase Create(Database context, PurchaseBindingModel model)
        {
            return new Purchase()
            {
                DatePurchase = DateTime.Now,
                UserId = Guid.NewGuid(),
                Status = PurchaseStatus.Unknown,

            };
        }
        public PurchaseBindingModel GetBindingModel => new()
		{
			Id = Id,
			DatePurchase = DatePurchase,
			UserId = UserId,
			PurchaseProducts = PurchaseProducts,
			Status = Status
		};

        public PurchaseViewModel GetViewModel => new()
        {
            Id = Id,
            DatePurchase = DatePurchase,
            UserId = UserId,
            PurchaseProducts = PurchaseProducts,
            Status = Status
        };

        public static Purchase ToPurchaseFromView(PurchaseViewModel model, Purchase purchase) => new()
		{
			Id = model.Id,
			DatePurchase = model.DatePurchase,
            UserId = model.UserId,
            PurchaseProducts = model.PurchaseProducts,
            Status = model.Status
        };

		public static Purchase ToPurchaseFromBinding(PurchaseBindingModel model, Purchase purchase) => new()
		{
			Id = model.Id,
			DatePurchase = model.DatePurchase,
            UserId = model.UserId,
            PurchaseProducts = model.PurchaseProducts,
            Status = model.Status
        };

		public void Update(PurchaseBindingModel model)
		{
			if (model is null)
			{
				throw new ArgumentNullException("Update purchase: binding model is null");
			}

			DatePurchase = model.DatePurchase;
            UserId = model.UserId;
            PurchaseProducts = model.PurchaseProducts;
            Status = model.Status;
		}
        public void UpdateProducts(Database context, PurchaseBindingModel model)
        {
            var purchaseProducts = context.PurchaseProducts.Where(rec =>
            rec.Id == model.Id).ToList();
            if (purchaseProducts != null && purchaseProducts.Count > 0)
            { // удалили те, которых нет в модели
                context.PurchaseProducts.RemoveRange(purchaseProducts.Where(rec
                => !model.PurchaseProducts.ContainsKey(rec.ProductId)));
                context.SaveChanges();
                // обновили количество у существующих записей
                foreach (var updateProduct in purchaseProducts)
                {
                    updateProduct.Count = model.PurchaseProducts[updateProduct.ProductId].Item2;
                    model.PurchaseProducts.Remove(updateProduct.ProductId);
                }
                context.SaveChanges();
            }
            var purchase = context.Purchases.First(x => x.Id == Id);
            foreach (var pc in model.PurchaseProducts)
            {
                context.PurchaseProducts.Add(new PurchaseProducts
                {
                    Purchase = purchase,
                    Product = context.Products.First(x => x.Id == pc.Key),
                    Count = pc.Value.Item2
                });
                context.SaveChanges();
            }
            _purchaseProducts = null;
        }

    }
}