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

namespace ComputerShopBusinessLogic.BusinessLogics
{
	public class AssemblyLogic : IAssemblyLogic
	{
		private readonly ILogger _logger;
		private readonly IAssemblyStorage _assemblyStorage;

		public AssemblyLogic(ILogger<AssemblyLogic> Logger, IAssemblyStorage AssemblyStorage)
		{
			_logger = Logger;
			_assemblyStorage = AssemblyStorage;
		}

		public List<AssemblyViewModel>? ReadList(AssemblySearchModel? Model)
		{
			var List = (Model == null) ? _assemblyStorage.GetFullList() : _assemblyStorage.GetFilteredList(Model);

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

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

		public AssemblyViewModel? ReadElement(AssemblySearchModel Model)
		{
			if (Model == null)
				throw new ArgumentNullException(nameof(Model));

			var Element = _assemblyStorage.GetElement(Model);
			if (Element == null)
			{
				_logger.LogWarning("ReadElement Assembly not found");
				return null;
			}

			_logger.LogInformation("ReadElement Assembly found. Id: {Id}", Element.Id);
			return Element;
		}

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

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

			return true;
		}

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

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

			return true;
		}

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

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

			return true;
		}

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

			if (!WithParams)
				return;

			if (string.IsNullOrEmpty(Model.AssemblyName))
				throw new ArgumentException($"У сборки отсутствует название");

			if (string.IsNullOrEmpty(Model.Category))
				throw new ArgumentException($"У сборки отсутствует категория");

			var Element = _assemblyStorage.GetElement(new AssemblySearchModel
			{
				AssemblyName = Model.AssemblyName
			});

			if (Element != null && Element.Id != Model.Id)
				throw new InvalidOperationException("Товар с таким названием уже есть");
		}
	}
}