using ComputerShopContracts.BindingModels;
using ComputerShopContracts.ViewModels;
using ComputerShopDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ComputerShopDatabaseImplement.Models
{
	public class Assembly : IAssemblyModel
	{
		public int Id { get; private set; }

		[Required]
		public int UserId { get; private set; }

		[Required]
		public string AssemblyName { get; private set; } = string.Empty;

		[Required]
		public double Price { get; private set; }

		[Required]
		public string Category { get; private set; } = string.Empty;

		[ForeignKey("AssemblyId")]
		public virtual List<Request> Requests { get; set; } = new();

		[ForeignKey("AssemblyId")]
		public virtual List<AssemblyComponent> Components { get; set; } = new();

		private Dictionary<int, (IComponentModel, int)>? _assemblyComponents;

		[NotMapped]
		public Dictionary<int, (IComponentModel, int)> AssemblyComponents
		{
			get
			{
				if (_assemblyComponents == null)
				{
					_assemblyComponents = Components.ToDictionary(
						AsmComp => AsmComp.ComponentId, 
						AsmComp => (AsmComp.Component as IComponentModel, AsmComp.Count)
					);
				}

				return _assemblyComponents;
			}
		}

		public static Assembly Create(ComputerShopDatabase Context, AssemblyBindingModel Model)
		{
			return new()
			{
				Id = Model.Id,
				UserId = Model.UserId,
				AssemblyName = Model.AssemblyName,
				Price = Model.Price,
				Category = Model.Category,
				Components = Model.AssemblyComponents.Select(x => new AssemblyComponent
				{
					Component = Context.Components.First(y => y.Id == x.Key),
					Count = x.Value.Item2
				}).ToList(),
			};
		}

		public void Update(AssemblyBindingModel Model)
		{
			if (!string.IsNullOrEmpty(Model.AssemblyName))
			{
				AssemblyName = Model.AssemblyName;
			}			
			
			if (!string.IsNullOrEmpty(Model.Category))
			{
				Category = Model.Category;
			}
			
			Price = Model.Price;
		}

		public AssemblyViewModel ViewModel => new()
		{
			Id = Id,
			UserId = UserId,
			AssemblyName = AssemblyName,
			Price = Price,
			Category = Category,
			AssemblyComponents = AssemblyComponents,
		};

		public void UpdateComponents(ComputerShopDatabase Context, AssemblyBindingModel Model)
		{
			var AssemblyComponents = Context.AssemblyComponents.Where(x => x.AssemblyId == Model.Id).ToList();
			if (AssemblyComponents != null && AssemblyComponents.Count > 0)
			{
				Context.AssemblyComponents
					.RemoveRange(AssemblyComponents
					.Where(x => !Model.AssemblyComponents.ContainsKey(x.ComponentId)));
				Context.SaveChanges();

				foreach (var ComponentToUpdate in AssemblyComponents)
				{
					ComponentToUpdate.Count = Model.AssemblyComponents[ComponentToUpdate.ComponentId].Item2;
					Model.AssemblyComponents.Remove(ComponentToUpdate.ComponentId);
				}

				Context.SaveChanges();
			}

			var CurrentAssembly = Context.Assemblies.First(x => x.Id == Id);
			foreach (var AssemblyComponent in Model.AssemblyComponents)
			{
				Context.AssemblyComponents.Add(new AssemblyComponent
				{
					Assembly = CurrentAssembly,
					Component = Context.Components.First(x => x.Id == AssemblyComponent.Key),
					Count = AssemblyComponent.Value.Item2
				});

				Context.SaveChanges();
			}

			_assemblyComponents = null;
		}
	}
}