using Contracts.BindingModels;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using DatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DatabaseImplement.Implements
{
    public class UserStorage : IUserStorage
    {
        public UserBindingModel? Delete(UserSearchModel model)
        {
            if (model.Id is null && model.Email is null)
            {
                return null;
            }

            var context = new Database();
            var user = context.Users.FirstOrDefault(u =>
                (model.Id.HasValue && u.Id == model.Id)
                || (!string.IsNullOrEmpty(u.Email) && u.Email.Contains(model.Email)));

            if (user is null)
            {
                return null;
            }
            context.Remove(user);
            context.SaveChanges();

            return user.GetBindingModel();
        }

        public UserBindingModel? GetElement(UserSearchModel model)
        {
            if (model.Id is null && model.Email is null)
            {
                return null;
            }
            var context = new Database();
            return context.Users
                .Include(u => u.Role)
                .FirstOrDefault(u =>
                    (model.Id.HasValue && u.Id == model.Id)
                    || (!string.IsNullOrEmpty(u.Email) && u.Email.Contains(model.Email)))
                ?.GetBindingModel();
        }

        public IEnumerable<UserBindingModel> GetList(UserSearchModel? model)
        {
            var context = new Database();
            if (model is null)
            {
                return context.Users
                    .Include(u => u.Role)
                    .Select(r => r.GetBindingModel());
            }
            if (model.Id is null && model.Email is null && !model.OnlyImportantMails is null)
            {
                return [];
            }
            return context.Users
                .Where(u =>
                    (model.Id.HasValue && u.Id == model.Id)
                    || (!string.IsNullOrEmpty(u.Email) && u.Email.Contains(model.Email))
                    || (model.OnlyImportantMails.HasValue && u.OnlyImportantMails == model.OnlyImportantMails))
                .Include(u => u.Role)
                .Select(r => r.GetBindingModel());
        }

        public UserBindingModel? Insert(UserBindingModel model)
        {
            var context = new Database();
            var role = context.Roles.FirstOrDefault(r => r.Id == model.Role.Id);
            if (role is null)
            {
                return null;
            }
            var newUser = Models.User.ToUserFromBinding(model, role);

            context.Users.Add(newUser);
            context.SaveChanges();

            return newUser.GetBindingModel();
        }

        public UserBindingModel? Update(UserBindingModel model)
        {
            var context = new Database();
            var user = context.Users
                .FirstOrDefault(u => u.Id == model.Id);
            var role = context.Roles.FirstOrDefault(r => r.Id == model.Role.Id);

            if (user is null || role is null)
            {
                return null;
            }

            user.Update(model, role);

            context.SaveChanges();
            return user.GetBindingModel();
        }

        public void UpdateBonus(BonusUpdateBindingModel model)
        {
            var context = new Database();
            var user = context.Users
                .FirstOrDefault(u => u.Id == model.UserId);

            if (user is null)
                return;

            user.Bonus += model.BonusPlus;
            user.Bonus -= model.BonusMinus;

            context.SaveChanges();
        }
    }
}