using BankContracts.BindingModels;
using BankContracts.ViewModels;
using BankDataModels.Models;
using Microsoft.Identity.Client;
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 BankDatabaseImplement.Models
{
    public class Payment : IPaymentModel
    {
        public int Id { get; set; }
        [Required]
        public DateTime PaymentDate { get; set; } = DateTime.Now;
        private Dictionary<int, IDealModel>? _dealPayments = null;
        [NotMapped]
        public Dictionary<int, IDealModel> DealPayments {
            get
            {
                if (_dealPayments == null)
                {
                    _dealPayments = Deals.ToDictionary(recDP => recDP.DealId, recDP => recDP.Deal as IDealModel);
                }
                return _dealPayments;
            } 
        }
        [ForeignKey("PaymentId")]
        public virtual List<DealPayment> Deals { get; set; } = new();
        private Dictionary<int, ICurrencyModel>? _currencyPayments = null;
        [NotMapped]
        public Dictionary<int, ICurrencyModel> CurrencyPayments
        {
            get
            {
                if (_currencyPayments == null)
                {
                    _currencyPayments = Currencies.ToDictionary(recCP => recCP.CurrencyId, recCP => recCP.Currency as ICurrencyModel);
                }
                return _currencyPayments;
            }
        }
        public virtual List<CurrencyPayment> Currencies { get; set; } = new();

        public int OperatorId { get; set; }
        public virtual Operator Operator { get; set; } = new();

        public static Payment? Create(BankDatabase context, PaymentBindingModel model)
        {
            if (model == null)
            {
                return null;
            }
            return new Payment()
            {
                Id = model.Id,
                PaymentDate = model.PaymentDate,
                Deals = model.DealPayments.Select(x => new DealPayment
                {
                    Deal = context.Deals.First(y => y.Id == x.Key)
                }).ToList()
            };
        }
        public void Update(PaymentBindingModel? model)
        {
            if (model == null)
            {
                return;
            }
            PaymentDate = model.PaymentDate;
        }
        public PaymentViewModel GetViewModel => new()
        {
            Id = Id,
            PaymentDate = PaymentDate,
            DealPayments = DealPayments,
            CurrencyPayments = CurrencyPayments,
            OperatorId = OperatorId,
            OperatorName = Operator.LastName + " " + Operator.FirstName + " " + Operator.MiddleName,
        };
        public void UpdateDeals(BankDatabase context, PaymentBindingModel model)
        {
            var dealPayments = context.DealPayments.Where(rec => rec.PaymentId == model.Id).ToList();
            if (dealPayments != null && dealPayments.Count > 0)
            {
                context.DealPayments.RemoveRange(dealPayments.Where(rec => !model.DealPayments.ContainsKey(rec.DealId)));
                context.SaveChanges();
                var payment = context.Payments.First(x => x.Id == Id);
                foreach (var updateIngredient in dealPayments)
                {
                    model.DealPayments.Remove(updateIngredient.DealId);
                }
                foreach (var dp in model.DealPayments)
                {
                    context.DealPayments.Add(new DealPayment
                    {
                        Payment = payment,
                        Deal = context.Deals.First(x => x.Id == dp.Key),
                    });
                    context.SaveChanges();
                }
                _dealPayments = null;
            }
        }
        public void UpdateCurrencies(BankDatabase context, PaymentBindingModel model)
        {
            var currencyPayments = context.CurrencyPayments.Where(rec => rec.PaymentId == model.Id).ToList();
            if (currencyPayments != null && currencyPayments.Count > 0)
            {
                context.CurrencyPayments.RemoveRange(currencyPayments.Where(rec => !model.CurrencyPayments.ContainsKey(rec.CurrencyId)));
                context.SaveChanges();
                var payment = context.Payments.First(x => x.Id == Id);
                foreach (var updateIngredient in currencyPayments)
                {
                    model.CurrencyPayments.Remove(updateIngredient.CurrencyId);
                }
                foreach (var cp in model.CurrencyPayments)
                {
                    context.CurrencyPayments.Add(new CurrencyPayment
                    {
                        Payment = payment,
                        Currency = context.Currencies.First(x => x.Id == cp.Key),
                    });
                    context.SaveChanges();
                }
                _currencyPayments = null;
            }
        }
    }
}
