using ComputerHardwareStoreContracts.BindingModels;
using ComputerHardwareStoreContracts.ViewModels;
using ComputerHardwareStoreDataModels.Models;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.InteropServices;

namespace ComputerHardwareStoreDatabaseImplement.Models
{
    public class Build : IBuildModel
    {
        public int Id { get; set; }
        [Required]
        public string Name { get; set; } = string.Empty;
        [Required]
        public double Price { get; set; }

        private Dictionary<int, (IComponentModel, int)>? _buildComponents = null;
        [NotMapped]
        public Dictionary<int, (IComponentModel, int)> BuildComponents
        {
            get
            {
                if (_buildComponents == null)
                {
                    _buildComponents = Components
                        .ToDictionary(bc => bc.ComponentId, bc =>
                        (bc.Component as IComponentModel, bc.Count));
                }
                return _buildComponents;
            }   
        }
        [ForeignKey("BuildId")]
        public virtual List<BuildComponent> Components { get; set; } = new();
        [ForeignKey("BuildId")]

        public virtual List<Comment> Comments { get; set; } = new();
        [NotMapped]
        List<ICommentModel> IBuildModel.Comments => Comments.Select(c => c as ICommentModel).ToList();

        public virtual Vendor Vendor { get; private set; } = new();
        IVendorModel IBuildModel.Vendor => Vendor as IVendorModel;

        public static Build? Create(ComputerHardwareStoreDBContext context, BuildBindingModel model)
        {
            if (model == null)
            {
                return null;
            }
            return new()
            {
                Id = model.Id,
                Name = model.Name,
                Price = model.Price,
                Vendor = context.Vendors.First(v => v.Id == model.Vendor.Id),
                Components = context.Components
                    .Where(c => model.BuildComponents.ContainsKey(c.Id))
                    .Select(c => new BuildComponent()
                    {
                        BuildId = model.Id,
                        ComponentId = c.Id,
                        Component = c,
                        Count = model.BuildComponents[c.Id].Item2
                    }).ToList()
            };
        }

        public void Update(BuildBindingModel model)
        {
            if (model == null)
            {
                return;
            }
            Name = string.IsNullOrEmpty(model.Name) ? Name : model.Name;
            Price = model.Price;
        }

        public BuildViewModel GetViewModel() => new()
        {
            Id = Id,
            Name = Name,
            Price = Price,
            Vendor = Vendor,
            Comments = Comments.Select(c => c as ICommentModel).ToList(),
            BuildComponents = BuildComponents
        };
    }
}