using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using ComputerStoreDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComputerStoreDatabaseImplement.Models
{
    public class PC : IPCModel
    {
        public int ID { get; private set; }

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

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

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

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

        private Dictionary<int, (IComponentModel, int)>? _pcComponents = null;


        [NotMapped]
        public Dictionary<int, (IComponentModel, int)> PCComponents
        {
            get
            {
                if(_pcComponents == null)
                {
                    _pcComponents = Components.ToDictionary(recPC => recPC.ComponentID, recPC => (recPC.Component as IComponentModel, recPC.Count));
                }
                return _pcComponents;
            }
        }

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

        public virtual Employee Employee { get; set; }

        public static PC Create(ComputerStoreDatabase context, PCBindingModel model)
        {
            return new PC()
            {
                ID = model.ID,
                Name = model.Name,
                Price = model.Price,
                EmployeeID = model.EmployeeID,
                RequestID = model.RequestID,
                Components = model.PCComponents.Select(x => new RequestComponent
                {
                    Component = context.Components.First(y => y.ID == x.Key),
                    Count = x.Value.Item2
                }).ToList()
            };
        }

        public void Update(PCBindingModel model)
        {
            Name = model.Name;
            Price = model.Price;
        }

        public PCViewModel GetViewModel => new()
        {
            ID = ID,
            Name = Name,
            Price = Price,
            EmployeeID = EmployeeID,
            EmployeeUsername = Employee.Username,
            RequestID = RequestID,
            PCComponents = PCComponents
        };

        public void UpdateComponents(ComputerStoreDatabase context, PCBindingModel model)
        {
            var pcComponents = context.RequestComponents.Where(rec => rec.PCID == model.ID && rec.RequestID == model.RequestID).ToList();
            if(pcComponents != null &&  pcComponents.Count > 0)
            {
                context.RequestComponents.RemoveRange(pcComponents.Where(rec => !model.PCComponents.ContainsKey(rec.ComponentID) && rec.RequestID == model.RequestID));
                context.SaveChanges();
                foreach(var updateComponent  in pcComponents)
                {
                    updateComponent.Count = model.PCComponents[updateComponent.PCID].Item2;
                    model.PCComponents.Remove(updateComponent.PCID);
                }
                context.SaveChanges();
            }

            var pc = context.PCs.First(rec => model.ID == ID);
            foreach(var pcc in model.PCComponents )
            {
                context.RequestComponents.Add(new RequestComponent
                {
                    PC = pc,
                    Component = context.Components.First(x=> x.ID == pcc.Key),
                    Request = context.Requests.First(x => x.ID == model.RequestID),
                    Count = pcc.Value.Item2
                });
                context.SaveChanges();
            }
            _pcComponents = null;
        }

    }
}