namespace MyOffice.Services.Motion
{
	using MyOffice.Data.Repositories.Motion;
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;
	using System.Threading.Tasks;
	using Data.Models.Motions;
	using MyOffice.Core;
	using MyOffice.Services.Motion.Domain;

	public class MotionService
	{
		private readonly IMotionCategoryRepository _motionCategoryRepository;
		private readonly IMotionRepository _motionRepository;

		public MotionService(
			IMotionCategoryRepository motionCategoryRepository,
			IMotionRepository motionRepository
		)
		{
			_motionCategoryRepository = motionCategoryRepository;
			_motionRepository = motionRepository;

		}

		public List<MotionCategory> GetAllCategories(Guid userId)
		{
			var result = _motionCategoryRepository.GetAll(userId);
			if (result.All(x => x.Id != userId))
			{
				var category = new MotionCategory
				{
					Id = userId,
					UserId = userId,
					Name = "UnCategorized",
				};
				_motionCategoryRepository.Add(category);
				
				result.Add(_motionCategoryRepository.Get(userId, userId)!);
			}
			return result;
		}

		public Exec<MotionCategory, GeneralExecStatus> CategoryAdd(Guid userId, MotionCategory category)
		{
			if (category == null)
				throw new ArgumentNullException(nameof(category));

			var result = new Exec<MotionCategory, GeneralExecStatus>(GeneralExecStatus.success);

			category.Id = Guid.NewGuid();
			category.UserId = userId;

			if (!_motionCategoryRepository.Add(category))
			{
				return result.Set(GeneralExecStatus.failure);
			}

			return result.Set(category);
		}

		public Exec<MotionCategory, GeneralExecStatus> CategoryUpdate(Guid userId, Guid id, MotionCategory category)
		{
			if (category == null)
				throw new ArgumentNullException(nameof(category));

			var result = new Exec<MotionCategory, GeneralExecStatus>(GeneralExecStatus.success);

			var exists = _motionCategoryRepository.Get(userId, id);
			if (exists == null)
			{
				return result.Set(GeneralExecStatus.not_found);
			}

			exists.Name = category.Name;

			if (!_motionCategoryRepository.Update(exists))
			{
				return result.Set(GeneralExecStatus.failure);
			}

			return result.Set(exists);
		}

		public Exec<MotionCategory, MotionCategoryRemoveResult> CategoryRemove(Guid userId, Guid id)
		{
			var result = new Exec<MotionCategory, MotionCategoryRemoveResult>(MotionCategoryRemoveResult.success);

			var exists = _motionCategoryRepository.Get(userId, id);
			if (exists == null)
			{
				return result.Set(MotionCategoryRemoveResult.not_found);
			}

			if (exists.Motions.Any())
			{
				return result.Set(MotionCategoryRemoveResult.accounts_exists);
			}
			if (!_motionCategoryRepository.Remove(exists))
			{
				return result.Set(MotionCategoryRemoveResult.failure);
			}

			return result.Set(exists);
		}

		public List<MotionAccount> GetAll(Guid userId)
		{
			return _motionRepository.GetAll(userId);
		}

		public List<MotionAccount> GetByCategory(Guid userId, Guid categoryId)
		{
			return _motionRepository.GetByCategory(userId, categoryId);
		}

		public Exec<MotionAccount, GeneralExecStatus> Update(Guid userId, Guid motionId, Guid categoryId)
		{
			var result = new Exec<MotionAccount, GeneralExecStatus>(GeneralExecStatus.success);

			var motion = _motionRepository.GetByGlobal(userId, motionId);
			if (motion == null)
			{
				return result.Set(GeneralExecStatus.not_found);
			}

			motion.Category.Id = categoryId;
			//motion.CategoryId = categoryId;
			_motionRepository.Update(motion);

			return result.Set(motion);
		}
	}
}
