using Contracts.BindingModels;
using Contracts.BusinessLogicsContracts;
using Contracts.SearchModels;
using Contracts.StoragesContracts;
using Contracts.ViewModels;
using Microsoft.Extensions.Logging;

namespace BusinessLogic.BusinessLogic
{
	public class ImplementerLogic : IImplementerLogic
	{
		private readonly ILogger _logger;
		private readonly IImplementerStorage _storage;

		public ImplementerLogic(ILogger<ImplementerLogic> logger, IImplementerStorage storage)
		{
			_logger = logger;
			_storage = storage;
		}
		public List<ImplementerViewModel>? ReadList(ImplementerSearchModel? model)
		{
			_logger.LogInformation("ReadList. Login:{Login}. Id:{Id}", model!.Login, model.Id);
			var list = model == null ? _storage.GetFullList() : _storage.GetFilteredList(model);
			if (list == null)
			{
				_logger.LogWarning("ReadList return null");
				return null;
			}
			return list;
		}
		public ImplementerViewModel? ReadElement(ImplementerSearchModel? model) 
		{ 
			if (model == null)
			{
				throw new ArgumentNullException(nameof(model));
			}
			_logger.LogInformation("ReadElement. Login:{Login}. Id:{Id}.", model.Login, model.Id);
			var elem = _storage.GetElement(model);
			if (elem == null)
			{
				_logger.LogWarning("ReadElement element not found");
				return null;
			}
			_logger.LogInformation("ReadElement find. Id:{Id}", elem.Id);
			return elem;
		}
		private void CheckModel(ImplementerBindingModel? model, bool withParams = true) 
		{ 
			if (model == null)
			{
				throw new ArgumentNullException(nameof (model));
			}
			if (!withParams)
				return;
			if (string.IsNullOrEmpty(model.Name))
			{
				throw new ArgumentNullException("Нет имени пользователя", nameof (model));
			}
			if (string.IsNullOrEmpty(model.Login))
			{
				throw new ArgumentNullException("Нет логина пользователя", nameof(model));
			}
			if (string.IsNullOrEmpty(model.Password))
			{
				throw new ArgumentNullException("Нет пароля пользователя", nameof(model));
			}
			if (string.IsNullOrEmpty(model.Email))
			{
				throw new ArgumentNullException("Нет почты пользователя", nameof(model));
			}
			var elem = _storage.GetElement(new ImplementerSearchModel
			{
				Login = model.Login
			});
			if (elem != null && model.Id != elem.Id)
			{
				throw new InvalidOperationException("Такой логин уже используется в системе");
			}
		}
		public bool Create(ImplementerBindingModel? model)
		{
			CheckModel(model);
			if (_storage.Insert(model!) == null)
			{
				_logger.LogWarning("Insert error");
				return false;
			}
			return true;
		}
		public bool Update(ImplementerBindingModel? model)
		{
			CheckModel(model);
			if (_storage.Update(model!) == null)
			{
				_logger.LogWarning("Update error");
				return false;
			}
			return true;
		}
		public bool Delete(ImplementerBindingModel? model)
		{
			CheckModel(model, false);
			_logger.LogInformation("Delete Implementer. Id:{Id}", model!.Id);
			if (_storage.Delete(model!) == null)
			{
				_logger.LogWarning("Delete error");
				return false;
			}
			return true;
		}
	}
}
