using BankContracts.BindingModels;
using BankContracts.ViewModels;
using BankDataModels;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq.Expressions;
using BankDataModels.ProxyModels;

namespace BankDatabaseImplement.Models
{
    public class Purchase : IPurchaseModel
    {
        public int ClientId { get; private set; }
        public DateOnly DatePurchase { get; private set; }
        private Dictionary<int, OperationByPurchaseModel>? _cachedOperations;
        [NotMapped]
        public Dictionary<int, OperationByPurchaseModel> OperationsModel => _cachedOperations ??= Operations.Select(x => (OperationByPurchaseModel)x).ToDictionary(x => x.OperationId, x => x);
        [NotMapped]
        public List<CostByPurchaseModel>? CostsModel => null;
        public int Id { get; private set; }
        [Required]
        public Client? Client { get; private set; }
        [Required]
        public List<OperationByPurchase> Operations { get; private set; } = new();
        [Required]
        public List<CostByPurchase> Costs { get; private set; } = new();

        public static Purchase Create(PurchaseBindingModel model)
        {
            return new Purchase()
            {
                ClientId = model.ClientId,
                Id = model.Id,
                DatePurchase = model.DatePurchase,

            };
        }
        public void Update(PurchaseBindingModel model)
        {
            DatePurchase = model.DatePurchase;
        }

        public PurchaseViewModel GetViewModel => new()
        {
            OperationsModel = OperationsModel,
            Id = Id,
            DatePurchase = DatePurchase,
            ClientId = ClientId,
            ClientPhoneNumber = Client?.PhoneNumber ?? string.Empty,

            CostViewModels = Costs?
                .Select(x => x.Cost.GetViewModel)
                .ToList() ?? new(),
            OperationViewModels = Operations?
                .Select(x => x.Operation?.GetViewModel)
                .ToList() ?? new()
        };

        public PurchaseViewModel GetViewModel2 => new()
        {
            OperationsModel = OperationsModel,
            Id = Id,
            DatePurchase = DatePurchase,
            ClientId = ClientId,
            ClientPhoneNumber = Client?.PhoneNumber ?? string.Empty,

            CostViewModels = Costs?
                .Select(x => x.Cost.GetViewModel)
                .ToList() ?? new()
        };

        public void UpdateOperations(BankDB context, PurchaseBindingModel model)
        {
            var oldOperations = context.OperationByPurchases.Where(x => x.PurchaseId == model.Id).ToDictionary(x => x.OperationId, x => x);
            var newOperations = model.OperationsModel.ToDictionary(
                x => x.Key,
                x => new OperationByPurchase()
                {
                    OperationId = x.Key,
                    PurchaseId = Id,
                    CountOperations = x.Value.CountOperations
                }
                );

            context.RemoveRange(oldOperations.Where(x => !newOperations.ContainsKey(x.Key)).Select(x => x.Value));
            context.AddRange(newOperations.Where(x => !oldOperations.ContainsKey(x.Key)).Select(x => x.Value));
            oldOperations
                .Where(x => newOperations.ContainsKey(x.Key))
                .Select(x => x.Value).ToList()
                .ForEach(x => x.CountOperations = newOperations[x.OperationId].CountOperations);
            context.SaveChanges();
            _cachedOperations = null;
        }
    }
}
