using Contracts.BindingModels;
using Contracts.BusinessLogicContracts;
using Contracts.Converters;
using Contracts.Exceptions;
using Contracts.SearchModels;
using Contracts.StorageContracts;
using Contracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BusinessLogic.BusinessLogic
{
	public class RoleLogic : IRoleLogic
	{
		private readonly ILogger _logger;
		private readonly IRoleStorage _roleStorage;

		public RoleLogic(ILogger<RoleLogic> logger, IRoleStorage roleStorage)
		{
			_logger = logger;
			_roleStorage = roleStorage;
		}

		public RoleViewModel Create(RoleBindingModel model)
		{
			ArgumentNullException.ThrowIfNull(model);

			var role = _roleStorage.Insert(model);
			if (role is null)
			{
				throw new Exception("Insert operation failed.");
			}

			return RoleConverter.ToView(role);
		}

		public RoleViewModel Delete(RoleSearchModel model)
		{
			ArgumentNullException.ThrowIfNull(model);

			_logger.LogInformation("Delete role. Id: {0}", model.Id);
			var role = _roleStorage.Delete(model);
			if (role is null)
			{
				throw new Exception("Delete operation failed.");
			}

			return RoleConverter.ToView(role);
		}

		public RoleViewModel ReadElement(RoleSearchModel model)
		{
			ArgumentNullException.ThrowIfNull(model);

			_logger.LogInformation("ReadElement. Id: {0}", model.Id);
			var role = _roleStorage.GetElement(model);
			if (role is null)
			{
				throw new ElementNotFoundException();
			}
			_logger.LogInformation("ReadElement find. Id: {0}", role.Id);

			return RoleConverter.ToView(role);
		}

		public IEnumerable<RoleViewModel> ReadElements(RoleSearchModel? model)
		{
			_logger.LogInformation("ReadList. Id: {Id}", model?.Id);
			var list = _roleStorage.GetList(model);
			if (list is null || list.Count() == 0)
			{
				_logger.LogWarning("ReadList return null list");
				return [];
			}
			_logger.LogInformation("ReadList. Count: {Count}", list.Count());

			return list.Select(RoleConverter.ToView);
		}

		public RoleViewModel Update(RoleBindingModel model)
		{
			ArgumentNullException.ThrowIfNull(model);

			var role = _roleStorage.Update(model);
			if (role is null)
			{
				throw new Exception("Update operation failed.");
			}
			return RoleConverter.ToView(role);
		}
	}
}