using ComputerShopContracts.BindingModels;
using ComputerShopContracts.BusinessLogicContracts;
using ComputerShopContracts.SearchModels;
using ComputerShopContracts.StorageContracts;
using ComputerShopContracts.ViewModels;
using Microsoft.Extensions.Logging;

namespace ComputerShopBusinessLogic.BusinessLogics
{
	public class ComponentLogic : IComponentLogic
	{
		private readonly ILogger _logger;
		private readonly IComponentStorage _componentStorage;

		public ComponentLogic(ILogger<ComponentLogic> Logger, IComponentStorage ComponentStorage)
		{
			_logger = Logger;
			_componentStorage = ComponentStorage;
		}

		public List<ComponentViewModel>? ReadList(ComponentSearchModel? Model)
		{
			var List = (Model == null) ? _componentStorage.GetFullList() : _componentStorage.GetFilteredList(Model);

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

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

		public ComponentViewModel? ReadElement(ComponentSearchModel Model)
		{
			if (Model == null)
				throw new ArgumentNullException(nameof(Model));

			var Element = _componentStorage.GetElement(Model);
			if (Element == null)
			{
				_logger.LogWarning("ReadElement component not found");
				return null;
			}
			
			_logger.LogInformation("ReadElement component found. Id: {Id}", Element.Id);
			return Element;
		}

		public bool Create(ComponentBindingModel Model)
		{
			CheckModel(Model);

			if (_componentStorage.Insert(Model) == null)
			{
				_logger.LogWarning("Insert operation failed");
				return false;
			}

			return true;
		}

		public bool Update(ComponentBindingModel Model)
		{
			CheckModel(Model);

			if (_componentStorage.Update(Model) == null)
			{
				_logger.LogWarning("Update operation failed");
				return false;
			}

			return true;
		}

		public bool Delete(ComponentBindingModel Model)
		{
			CheckModel(Model, false);
			_logger.LogInformation("Delete. Id:{Id}", Model.Id);

			if (_componentStorage.Delete(Model) is null)
			{
				_logger.LogWarning("Delete operation failed");
				return false;
			}

			return true;
		}

		private void CheckModel(ComponentBindingModel Model, bool WithParams = true)
		{
			if (Model == null)
				throw new ArgumentNullException(nameof(Model));

			if (!WithParams)
				return;

			if (string.IsNullOrEmpty(Model.ComponentName))
				throw new ArgumentException($"У комплектующей отсутствует название");

			if (Model.Cost <= 0)
				throw new ArgumentException("Цена комплектующей должна быть больше 0", nameof(Model.Cost));

			var Element = _componentStorage.GetElement(new ComponentSearchModel
			{
				ComponentName = Model.ComponentName
			});

			if (Element != null && Element.Id != Model.Id)
				throw new InvalidOperationException("Комплектующая с таким названием уже есть");
		}
	}
}