/// <summary>Accepts the status.</summary>
        /// <param name="ownerToken"></param>
        /// <param name="acceptRequest">The accept request.</param>
        /// <returns></returns>
        public async Task <OperationResult> AcceptStatusAsync(string ownerToken, AcceptRequest acceptRequest)
        {
            AcceptChangeResponse statusChangeResponse =
                statusChangeRepository.TryAcceptChangeRequest(acceptRequest.MedicalCode, expirationPeriodInHours);

            switch (statusChangeResponse.Result)
            {
            case AcceptChangeResult.MissingCode:
            case AcceptChangeResult.ReusedCode:
                return(OperationResult.CreateInstance(StatusCodes.Status404NotFound, "Medical code not found or already taken."));

            case AcceptChangeResult.ExpiredCode:
                return(OperationResult.CreateInstance(StatusCodes.Status406NotAcceptable, "Medical code is expired."));
            }

            // Try upload all meetings to blob
            await blobStorageService.UploadMeetingsToContainer(ownerToken, acceptRequest);

            // Mark the change request as accepted
            var userStatus = new UserStateStatus
            {
                UserToken       = ownerToken,
                StatusId        = statusChangeResponse.StatusId,
                StatusChangedOn = statusChangeResponse.StatusChangedOn
            };

            // Update user status
            userRepository.SetUserStatus(userStatus);

            return(OperationResult.CreateInstance(StatusCodes.Status200OK));
        }
        public void TestStatusChangeAccept()
        {
            var medicalCode      = "ABC123";
            var infectedStatusId = 1;
            var repository       = ServiceProvider.GetService <IStatusChangeRepository>();
            var changeRequest    = new StatusChangeRequest(infectedStatusId, new DateTime(2020, 4, 1), "Comment");

            Assert.That(repository.TryCreateChangeRequest(medicalCode, changeRequest, "medicalUserToken"),
                        Is.True, "Creating a new code is successful");

            Assert.That(repository.TryAcceptChangeRequest(medicalCode + "invalid", 24),
                        Is.EqualTo(AcceptChangeResponse.Error(AcceptChangeResult.MissingCode)), "Accepting with missing code fails");

            Assert.That(repository.TryAcceptChangeRequest(medicalCode, 0),
                        Is.EqualTo(AcceptChangeResponse.Error(AcceptChangeResult.ExpiredCode)), "Accepting after expiration fails");

            Assert.That(repository.TryAcceptChangeRequest(medicalCode, 24),
                        Is.EqualTo(AcceptChangeResponse.Success(infectedStatusId, changeRequest.StatusChangedOn)),
                        "Accepting with good code succeeds");

            // verify that AcceptedAt is set
            var statusChange = new Table <StatusChange>(CassandraSession.Session)
                               .FirstOrDefault(row => row.MedicalCode == medicalCode)
                               .Execute();

            Assert.That(statusChange.AcceptedAt, Is.Not.Null);

            Assert.That(
                repository.TryAcceptChangeRequest(medicalCode, 24),
                Is.EqualTo(AcceptChangeResponse.Error(AcceptChangeResult.ReusedCode)), "Accepting with a taken code fails");
        }
        public AcceptChangeResponse TryAcceptChangeRequest(string medicalCode, int expirationHours)
        {
            var statusChange = new Table <StatusChange>(session)
                               .FirstOrDefault(row => row.MedicalCode == medicalCode)
                               .Execute();

            if (statusChange == null)
            {
                return(AcceptChangeResponse.Error(AcceptChangeResult.MissingCode));
            }
            if (statusChange.AcceptedAt != null)
            {
                return(AcceptChangeResponse.Error(AcceptChangeResult.ReusedCode));
            }

            if (statusChange.CreatedAt.AddHours(expirationHours) < DateTime.UtcNow)
            {
                return(AcceptChangeResponse.Error(AcceptChangeResult.ExpiredCode));
            }

            // CosmosDB doesn't support this Lightweight Transaction
            //return new Table<StatusChangeAccepted>(session)
            //    .Where(row => row.MedicalCode == medicalCode)
            //    .Select(row => new StatusChangeAccepted { AcceptedAt = DateTime.UtcNow })
            //    .UpdateIf(row => row.AcceptedAt == null)
            //    .Execute()
            //    .Applied;

            new Table <StatusChangeAccepted>(session)
            .Where(row => row.MedicalCode == medicalCode)
            .Select(row => new StatusChangeAccepted {
                AcceptedAt = DateTime.UtcNow
            })
            .Update()
            .Execute();

            return(AcceptChangeResponse.Success(statusChange.StatusId, statusChange.StatusChangedOn));
        }