using BankYouBankruptContracts.BindingModels;
using BankYouBankruptContracts.SearchModels;
using BankYouBankruptContracts.StoragesContracts;
using BankYouBankruptContracts.ViewModels.Client.Default;
using BankYouBankruptDatabaseImplement.Models;
using BankYouBankruptDataModels.Enums;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BankYouBankruptDatabaseImplement.Implements
{
    public class DebitingStorage : IDebitingStorage
    {

        public List<DebitingViewModel> GetFullList()
        {
            using var context = new BankYouBancruptDatabase();

            return context.Debitings
                    .Include(x => x.Card)
                    .Select(x => x.GetViewModel)
                    .ToList();
        }

        public List<DebitingViewModel> GetFilteredList(DebitingSearchModel model)
        {
            using var context = new BankYouBancruptDatabase();

            var result = context.Debitings.Include(x => x.Card).ToList();
                    
            //для получения всех заявок на стнятие со статусом "Открыта"
            if (model.Status.HasValue) result = result.Where(x => x.Status == model.Status).ToList();

            if (model.CardId.HasValue) result = result.Where(x => x.CardId == model.CardId).ToList();

            if (model.UserId.HasValue) { 
                List<int> cards = context.Cards.Where(x => x.ClientID == model.UserId).Select(x => x.Id).ToList();
                result = result.Where(x => cards.Contains(x.CardId)).ToList();
            }

			if (model.DateFrom.HasValue && model.DateTo.HasValue)
			{
				result = result.Where(x => x.DateOpen <= model.DateFrom && x.DateClose >= model.DateTo && x.Status != StatusEnum.Отклонено).ToList();
            }

            return result.Select(x => x.GetViewModel).ToList();
        }

        public DebitingViewModel? GetElement(DebitingSearchModel model)
        {
            if (model.CardId < 0 && !model.Id.HasValue)
            {
                return null;
            }

            using var context = new BankYouBancruptDatabase();

            return context.Debitings
				    .Include(x => x.Card)
					.FirstOrDefault(x => (!(model.CardId < 0) && x.CardId == model.CardId) ||
                                        (model.Id.HasValue && x.Id == model.Id))
                    ?.GetViewModel;
        }

        public DebitingViewModel? Insert(DebitingBindingModel model)
        {
            using var context = new BankYouBancruptDatabase();

            var newDebiting = Debiting.Create(context, model);

            if (newDebiting == null)
            {
                return null;
            }

            context.Debitings.Add(newDebiting);
            context.SaveChanges();

            return newDebiting.GetViewModel;
        }

        public DebitingViewModel? Update(DebitingBindingModel model)
        {
            using var context = new BankYouBancruptDatabase();
            using var transaction = context.Database.BeginTransaction();

            try
            {
                var debiting = context.Debitings.FirstOrDefault(rec => rec.Id == model.Id);

                if (debiting == null && debiting.Status == StatusEnum.Закрыта)
                {
                    return null;
                }

                debiting.Update(model);
                context.SaveChanges();
                transaction.Commit();

                return context.Debitings
					.Include(x => x.Card)
					.FirstOrDefault(x => x.Id == model.Id)
					?.GetViewModel;
			}
            catch
            {
                transaction.Rollback();
                throw;
            }
        }

        public DebitingViewModel? Delete(DebitingBindingModel model)
        {
            using var context = new BankYouBancruptDatabase();
            var element = context.Debitings
                .Include(x => x.CardId)
                .FirstOrDefault(rec => rec.Id == model.Id);

            if (element != null)
            {
                context.Debitings.Remove(element);
                context.SaveChanges();

                return element.GetViewModel;
            }

            return null;
        }
    }
}