public async Task <GetMemberStatsResponse> GetMemberStats(DateTime?startDate, DateTime?endDate)
        {
            loggingService.LogMethodInvoked();

            IList <ApiError> errors = new List <ApiError>();

            bool isNotPreparedToRun = await IsNotPreparedToGetMemberStats(startDate, endDate, errors);

            if (isNotPreparedToRun)
            {
                loggingService.LogMethodFinished();
                return(new GetMemberStatsResponse(errors));
            }

            DateTime startDateTime = startDate.GetValueOrDefault();
            DateTime endDateTime   = endDate.GetValueOrDefault();

            if (startDateTime.Date == startDateTime && startDateTime.Date == endDateTime)
            {
                startDateTime = startDateTime.Date.AddHours(12);
                endDateTime   = endDateTime.Date.AddHours(36);
            }

            IList <Member> members = await statsDownloadApiDataStoreService.GetMembers(startDateTime, endDateTime);

            var memberStatsResponse = new GetMemberStatsResponse(members);

            loggingService.LogMethodFinished();

            return(memberStatsResponse);
        }
        public async Task GetMemberStats_WhenNoStartDateIsProvided_ReturnsNoStartDateResponse()
        {
            GetMemberStatsResponse actual = await InvokeGetMemberStats(null, endDateMock);

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Errors?.Count, Is.EqualTo(1));
            Assert.That(actual.Errors?[0].ErrorCode, Is.EqualTo(ApiErrorCode.NoStartDate));
            Assert.That(actual.Errors?[0].ErrorMessage, Is.EqualTo(Constants.ErrorMessages.NoStartDateMessage));
        }
        public async Task GetMemberStats_WhenStartDateIsLaterThanEndDate_ReturnsInvalidDateRangeResponse()
        {
            GetMemberStatsResponse actual = await InvokeGetMemberStats(startDateMock, endDateMock.AddDays(-1));

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Errors?.Count, Is.EqualTo(1));
            Assert.That(actual.Errors?[0].ErrorCode, Is.EqualTo(ApiErrorCode.InvalidDateRange));
            Assert.That(actual.Errors?[0].ErrorMessage, Is.EqualTo(Constants.ErrorMessages.InvalidDateRangeMessage));
        }
        public async Task GetMemberStats_WhenEndDateInputIsTodayOrFutureDate_ReturnsEndDateUnsearchableResponse()
        {
            GetMemberStatsResponse actual = await InvokeGetMemberStats(startDateMock, DateTime.UtcNow);

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Errors?.Count, Is.EqualTo(1));
            Assert.That(actual.Errors?[0].ErrorCode, Is.EqualTo(ApiErrorCode.EndDateUnsearchable));
            Assert.That(actual.Errors?[0].ErrorMessage, Is.EqualTo(Constants.ErrorMessages.EndDateUnsearchableMessage));
        }
        public async Task GetMemberStats_WhenErrorsOccurs_ReturnsErrorsResponse()
        {
            statsDownloadApiDatabaseServiceMock
            .IsAvailable().Returns((false, DatabaseFailedReason.DatabaseUnavailable));

            GetMemberStatsResponse actual = await InvokeGetMemberStats(null, null);

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Members, Is.Null);
            Assert.That(actual.Errors?.Count, Is.EqualTo(3));
            Assert.That(actual.FirstErrorCode, Is.EqualTo(ApiErrorCode.NoStartDate));
        }
        public async Task GetMemberStats_WhenDataStoreIsUnavailable_ReturnsDataStoreUnavailableResponse()
        {
            statsDownloadApiDataStoreServiceMock.IsAvailable().Returns(false);

            GetMemberStatsResponse actual = await InvokeGetMemberStats();

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Errors?.Count, Is.EqualTo(1));
            Assert.That(actual.Errors?[0].ErrorCode, Is.EqualTo(ApiErrorCode.DataStoreUnavailable));
            Assert.That(actual.Errors?[0].ErrorMessage,
                        Is.EqualTo(Constants.ErrorMessages.DataStoreUnavailableMessage));
        }
        GetMemberStats_WhenDatabaseMissingRequiredObjects_ReturnsDatabaseMissingRequiredObjectsResponse()
        {
            statsDownloadApiDatabaseServiceMock
            .IsAvailable().Returns((false, DatabaseFailedReason.DatabaseMissingRequiredObjects));

            GetMemberStatsResponse actual = await InvokeGetMemberStats();

            Assert.That(actual.Success, Is.False);
            Assert.That(actual.Errors?.Count, Is.EqualTo(1));
            Assert.That(actual.Errors?[0].ErrorCode, Is.EqualTo(ApiErrorCode.DatabaseMissingRequiredObjects));
            Assert.That(actual.Errors?[0].ErrorMessage,
                        Is.EqualTo(Constants.ErrorMessages.DatabaseMissingRequiredObjectsMessage));
        }
        public async Task GetMemberStats_WhenInvoked_ReturnsSuccessMemberStatsResponse()
        {
            var members = new Member[2];

            statsDownloadApiDataStoreServiceMock.GetMembers(DateTime.MinValue, endDateMock).Returns(members);

            GetMemberStatsResponse actual = await InvokeGetMemberStats(DateTime.MinValue, endDateMock);

            Assert.That(actual.Success, Is.True);
            Assert.That(actual.Errors, Is.Null);
            Assert.That(actual.ErrorCount, Is.Null);
            Assert.That(actual.FirstErrorCode, Is.EqualTo(ApiErrorCode.None));
            Assert.That(actual.Members, Is.EqualTo(members));
            Assert.That(actual.MemberCount, Is.EqualTo(2));
        }