namespace MyOffice.Services.Account;

using MyOffice.Core;
using MyOffice.Data.Models.Accounts;
using MyOffice.Services.Account.Domain;

public partial class AccountService
{
	public List<AccountCategoryDto> GetAllCategories(Guid userId)
	{
		var categories = _accountCategoryRepository.GetAll(userId);

		return _mapper.Map<List<AccountCategoryDto>>(categories);
	}

	public Exec<AccountCategoryDto, GeneralExecStatus> GetCategory(Guid userId, Guid id)
	{
		var result = new Exec<AccountCategoryDto, GeneralExecStatus>(GeneralExecStatus.success);

		var category = _accountCategoryRepository.Get(userId, id);

		if (category == null)
		{
			return result.Set(GeneralExecStatus.not_found);
		}

		return result.Set(_mapper.Map<AccountCategoryDto>(category));
	}

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

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

		var category = new AccountCategory
		{
			Id = Guid.NewGuid(),
			UserId = userId,
			Name = input.Name,
		};

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

		return result.Set(_mapper.Map<AccountCategoryDto>(category));
	}

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

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

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

		exists.Name = input.Name;

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

		return result.Set(_mapper.Map<AccountCategoryDto>(exists));
	}

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

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

		if (exists.Accounts?.Any() == true)
		{
			return result.Set(AccountCategoryRemoveResult.accounts_exists);
		}
		if (!_accountCategoryRepository.Remove(exists))
		{
			return result.Set(AccountCategoryRemoveResult.failure);
		}

		return result.Set(_mapper.Map<AccountCategoryDto>(exists));
	}

	public Exec<List<AccountAccountCategoryDto>, GeneralExecStatus> AccountCategoryRemove(Guid userId, Guid accountId, Guid categoryId)
	{
		var result = new Exec<List<AccountAccountCategoryDto>, GeneralExecStatus>(GeneralExecStatus.success);

		var categories = _accountAccountCategoryRepository.Get(userId, accountId, categoryId);
		if (categories.Count == 0)
		{
			return result.Set(GeneralExecStatus.not_found);
		}

		foreach (var category in categories)
		{
			_accountAccountCategoryRepository.Remove(category);
		}

		return result.Set(_mapper.Map<List<AccountAccountCategoryDto>>(categories));
	}
}