private async Task <List <HandlerServiceResult> > ConfigureCategoryCurrency(string answer, User user)
        {
            answer = answer.Trim();

            if (string.IsNullOrEmpty(answer) || !answer.Equals("EUR") && !answer.Equals("USD") && !answer.Equals("BYN"))
            {
                return(new List <HandlerServiceResult>
                {
                    _resultService.BuildCategoryInvalidCurrencyErrorResult()
                });
            }

            var category = await _categoryDocumentService.GetByIdAsync(user.Context.CategoryId);

            category.Currency = answer;

            await _categoryDocumentService.UpdateAsync(category);

            user.Context.CurrentNode = user.Context.CurrentNode.Children.FirstOrDefault();

            await _userDocumentService.UpdateAsync(user);

            return(new List <HandlerServiceResult>
            {
                await _questionService.BuildQuestion(user)
            });
        }
        private async Task <List <HandlerServiceResult> > ConfigureCategoryDateRange(string answer, User user)
        {
            answer = answer.Trim();

            if (string.IsNullOrEmpty(answer))
            {
                return(new List <HandlerServiceResult>
                {
                    _resultService.BuildEmptyAnswerErrorResult()
                });
            }

            var category = await _categoryDocumentService.GetByIdAsync(user.Context.CategoryId);

            if (answer.Equals("All time"))
            {
                user.Context = null;

                await _userDocumentService.UpdateAsync(user);

                return(await _statsService.BuildStatistics(category));
            }

            try
            {
                var dateStrings = answer.Split('-');
                var from        = dateStrings[0].Split('.');
                var to          = dateStrings[1].Split('.');

                var fromDate = new DateTime(int.Parse(from[2]), int.Parse(from[1]), int.Parse(from[0]));
                var toDate   = new DateTime(int.Parse(to[2]), int.Parse(to[1]), int.Parse(to[0]));

                var operations = await _operationDocumentService.GetByCategoryId(category.Id);

                operations = operations.Where(o => o.Date >= fromDate && o.Date <= toDate).ToList();

                if (operations.Count == 0)
                {
                    return(new List <HandlerServiceResult>
                    {
                        _resultService.BuildStatsNoOperationsOnDateRangeErrorResult()
                    });
                }

                user.Context = null;
                await _userDocumentService.UpdateAsync(user);

                return(await _statsService.BuildStatistics(category, fromDate, toDate));
            }
            catch (Exception)
            {
                return(new List <HandlerServiceResult>
                {
                    _resultService.BuildOperationInvalidDateErrorResult()
                });
            }
        }
        private async Task <List <HandlerServiceResult> > ConfigureOperationSum(string answer, User user)
        {
            answer = answer.Trim();

            if (string.IsNullOrEmpty(answer) || !decimal.TryParse(answer, out decimal sum))
            {
                return(new List <HandlerServiceResult> {
                    _resultService.BuildOperationInvalidSumErrorResult()
                });
            }

            var result = new List <HandlerServiceResult>();

            var operation = await GetOrCreateOperationAsync(user);

            var category = await _categoryDocumentService.GetByIdAsync(operation.CategoryId);

            var sumInCents = (long)(sum * 100);

            if (category.Type == CategoryTypeEnum.Expense)
            {
                category.ExpenseInCents             += sumInCents;
                category.ExpenseForThisMonthInCents += sumInCents;

                if (category.ExpenseForThisMonthInCents > category.SupposedToSpentThisMonthInCents)
                {
                    result.Add(_resultService.BuildOperationExceededAmountForThisMonth(
                                   (float)(category.ExpenseForThisMonthInCents - category.SupposedToSpentThisMonthInCents) / 100));
                }
            }
            else
            {
                category.IncomeForThisMonthInCents += sumInCents;
                category.IncomeInCents             += sumInCents;
            }

            operation.CreditAmountInCents = sumInCents;

            await _operationDocumentService.UpdateAsync(operation);

            await _categoryDocumentService.UpdateAsync(category);

            user.Context.CurrentNode = user.Context.CurrentNode.Children.FirstOrDefault();

            var nextQuestion = await _questionService.BuildQuestion(user);

            await _userDocumentService.UpdateAsync(user);

            result.Add(nextQuestion);

            return(result);
        }
        public async Task <List <HandlerServiceResult> > Handle(Message message)
        {
            var user = await _userDocumentService.GetByChatId(message.UserInfo.ChatId);

            if (user.Context?.CategoryId != null)
            {
                var category = await _categoryDocumentService.GetByIdAsync(user.Context.CategoryId);

                if (!category.Configured)
                {
                    await _categoryDocumentService.DeleteAsync(user.Context.CategoryId);
                }
            }
            if (user.Context?.OperationId != null)
            {
                var operation = await _operationDocumentService.GetByIdAsync(user.Context.OperationId);

                if (!operation.Configured)
                {
                    await _operationDocumentService.DeleteAsync(user.Context.OperationId);
                }
            }

            if (user.Context == null)
            {
                user.Context = new Context();
            }

            user.Context.CurrentNode = null;
            user.Context.CategoryId  = null;
            user.Context.OperationId = null;

            await _userDocumentService.UpdateAsync(user);

            return(new List <HandlerServiceResult>
            {
                new HandlerServiceResult
                {
                    Message = "Command cancelled.",
                    StatusCode = StatusCodeEnum.Ok
                }
            });
        }