using BlacksmithWorkshopContracts.BindingModels;
using BlacksmithWorkshopContracts.BusinessLogicsContracts;
using BlacksmithWorkshopContracts.SearchModels;
using BlacksmithWorkshopContracts.StoragesContracts;
using BlacksmithWorkshopContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BlacksmithWorkshopBusinessLogic.BusinessLogic
{
	public class MessageInfoLogic : IMessageInfoLogic
	{
		private readonly ILogger _logger;

		private readonly IMessageInfoStorage _messageInfoStorage;

		public MessageInfoLogic(ILogger<MessageInfoLogic> logger, IMessageInfoStorage messageInfoStorage)
		{
			_logger = logger;
			_messageInfoStorage = messageInfoStorage;
		}

		public List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model)
		{
			_logger.LogInformation("ReadList. SenderName:{SenderName}. MessageId:{MessageId}", model?.SenderName, model?.MessageId);

			//list хранит весь список в случае, если model пришло со значением null на вход метода
			var list = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model);

			if (list == null)
			{
				_logger.LogWarning("ReadList return null list");
				return null;
			}

			_logger.LogInformation("ReadList. Count:{Count}", list.Count);

			return list;
		}

		public bool Create(MessageInfoBindingModel model)
		{
			CheckModel(model);

			if (_messageInfoStorage.Insert(model) == null)
			{
				_logger.LogWarning("Insert operation failed");

				return false;
			}

			return true;
		}

		//проверка входного аргумента для методов Insert, Update и Delete
		private void CheckModel(MessageInfoBindingModel model, bool withParams = true)
		{
			if (model == null)
			{
				throw new ArgumentNullException(nameof(model));
			}

			//так как при удалении передаём как параметр false
			if (!withParams)
			{
				return;
			}

			if (string.IsNullOrEmpty(model.MessageId))
			{
				throw new ArgumentNullException("Некорректный id письма", nameof(model.MessageId));
			}

			if (string.IsNullOrEmpty(model.SenderName))
			{
				throw new ArgumentNullException("Отсутствие заголовка у письма", nameof(model.SenderName));
			}

			if (string.IsNullOrEmpty(model.Subject))
			{
				throw new ArgumentNullException("Отсутствие сути у письма", nameof(model.Subject));
			}

			if (string.IsNullOrEmpty(model.Body))
			{
				throw new ArgumentNullException("Отсутствие тела у письма", nameof(model.Body));
			}

			if (model.DateDelivery >= DateTime.Now)
			{
				throw new ArgumentNullException("Некорректная дата отправки письма", nameof(model.DateDelivery));
			}

			_logger.LogInformation("Client. SenderName:{SenderName}. Subject:{Subject}. Body:{Body}. DateDelivery:{DateDelivery}. MessageId:{MessageId}.",
				model.SenderName, model.Subject, model.Body, model.DateDelivery, model.MessageId);

			//для проверка на наличие такого же аккаунта
			var element = _messageInfoStorage.GetElement(new MessageInfoSearchModel
			{
				SenderName = model.SenderName,
			});

			//если элемент найден и его Id не совпадает с Id переданного объекта
			if (element != null && element.MessageId.Contains(model.MessageId))
			{
				throw new InvalidOperationException("Аккаунт с таким логином уже есть");
			}
		}
	}
}
