using BarContracts.BindingModels;
using BarContracts.BusinessLogicContracts;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using Microsoft.Extensions.Logging;

namespace BarBusinessLogic.BusinessLogics
{
    public class ClientLogic : IClientLogic
    {
        private readonly ILogger _logger;
        private readonly IClientStorage _clientStorage;
        
        public ClientLogic(ILogger<ClientLogic> Logger, IClientStorage ClientStorage)
        {
            _logger = Logger;
            _clientStorage = ClientStorage;
        }
        
        public List<ClientViewModel>? ReadList(ClientSearchModel? Model)
        {
            _logger.LogInformation("ReadList. ClientFIO: {ClientFIO}. Id: {Id}", Model?.ClientFIO, Model?.Id);
            
            var List = Model == null ? _clientStorage.GetFullList() : _clientStorage.GetFilteredList(Model);
            if (List == null)
            {
                _logger.LogWarning("ReadList return null list");
                return null;
            }
            
            _logger.LogInformation("ReadList. Count: {Count}", List.Count);
            return List;
        }
        
        public ClientViewModel? ReadElement(ClientSearchModel Model)
        {
            if (Model == null)
                throw new ArgumentNullException(nameof(Model));

            _logger.LogInformation("ReadElement. ClientFIO: {ClientFIO}.Id: {Id}", Model.ClientFIO, Model.Id);
            
            ClientViewModel? Client = _clientStorage.GetElement(Model);
            if (Client == null)
            {
                _logger.LogWarning("ReadElement element not found");
                return null;
            }
            
            _logger.LogInformation("ReadElement find. Id: {Id}", Client.Id);
            return Client;
        }
        
        public bool Create(ClientBindingModel Model)
        {
            CheckModel(Model);
            
            if (_clientStorage.Insert(Model) == null)
            {
                _logger.LogWarning("Insert operation failed");
                return false;
            }
            
            return true;
        }
        
        public bool Update(ClientBindingModel Model)
        {
            CheckModel(Model);
            
            if (_clientStorage.Update(Model) == null)
            {
                _logger.LogWarning("Update operation failed");
                return false;
            }
            
            return true;
        }
        public bool Delete(ClientBindingModel Model)
        {
            CheckModel(Model, false);            
            _logger.LogInformation("Delete. Id:{Id}", Model.Id);
            
            if (_clientStorage.Delete(Model) == null)
            {
                _logger.LogWarning("Delete operation failed");
                return false;
            }
           
            return true;
        }
        
        private void CheckModel(ClientBindingModel Model, bool WithParams=true)
        {
            if (Model == null)
                throw new ArgumentNullException(nameof(Model));

            if (!WithParams)

            if (string.IsNullOrEmpty(Model.ClientFIO))
                throw new ArgumentNullException("Нет ФИО клиента", nameof(Model.ClientFIO));
            
            if (string.IsNullOrEmpty(Model.Email))
                throw new ArgumentNullException("Нет Email клиента", nameof(Model.ClientFIO));

            if (string.IsNullOrEmpty(Model.Password))
                throw new ArgumentNullException("Нет пароля клиента", nameof(Model.ClientFIO));

            _logger.LogInformation("Client. ClientFIO: {ClientFIO}." +
                "Email: {Email}. Password: {Password}. Id: {Id} ", Model.ClientFIO, Model.Email, Model.Password, Model.Id);
            
            ClientViewModel? Client = _clientStorage.GetElement(new ClientSearchModel
            {
                Email = Model.Email,
            });
            
            if (Client != null && Client.Id != Model.Id)
                throw new InvalidOperationException("Клиент с таким логином уже есть");
        }
    }
}
